
Im Grunde habe ich eine Reihe von Verzeichnissen, die ständig mit .rar-Dateien gefüllt werden, und ich muss in der Lage sein, sie an Ort und Stelle zu extrahieren, wobei die übrig gebliebenen .(rar|rXX)-Dateien automatisch gelöscht werden. Wie gehe ich dabei vor?
Hinweis: Ich kann sie nicht alle löschen, wenn sie einmal fertig sind. Sie müssen gelöscht werden, wenn das Skript einen seltenen Satz abschließt.
Beispiel einer Verzeichnisstruktur:
/
/folder1/
/file1.rar
/file1.r00
/file1.r01
/folder2/
/sub.folder1/
/file2.part001.rar (contains a directory "file2")
/file2.part002.rar
/file2.part003.rar
/sub.folder2/
/file3.rar
/file3.r00
/file3.r01
Erwartetes Ergebnis:
/
/folder1/
/file1.ext
/folder2/
/sub.folder1/
/file2/
/file2.ext
/sub.folder2/
/file3.ext
Antwort1
Variante für Bash:
#!/bin/bash
if [ ! -d "${1}" ]; then
printf '%s: error: mandatory argument is not a valid directory.' "${0##*/}" 1>&2
exit 1
fi
shopt -s extglob
for i in "${1}"/**/*.rar; do
cd -- "${i%/*}"
file=${i##*/}
unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
cd - >/dev/null
done
RAR-Archive können auch "legal" benannt werden, z. B. myarchive.part001.rar
und so weiter, und das müsste separat behandelt werden, wenn diese Art von Archiven existiert. Eine pragmatische Lösung besteht darin,
unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
mit
unrar e -o- -- "${file}"
if [ $? -eq 0 -o $? -eq 10 ]; then
rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
fi
Beachten Sie jedoch, dass hierdurch RAR-Dateien gelöscht werden, selbst wenn der Fehlercode 10 („Keine zu extrahierenden Dateien“) angezeigt wird. Daher wird die unveränderte Form im Allgemeinen nicht empfohlen.
Alles in allem ist es vielleicht besser, das Material einfach in der archivierten Form zu speichern und stattdessen bei Bedarf eine sofortige Dekomprimierung oder etwas Ähnliches zu verwenden. Das Beibehalten des archivierten Formats kann noch weitere Vorteile haben.
Antwort2
Ich schreibe das aus dem Stegreif, es ist also ungetesteter Code, aber er sollte Sie auf den richtigen Weg bringen. Er durchläuft im Grunde den Baum, auf den Sie zeigen, und sucht nach .rar-Dateien. Wenn er eine findet, wird er sie an Ort und Stelle dekomprimieren und das Originalarchiv löschen, es sei denn, unrar gibt einen Wert ungleich Null zurück. Wenn ein Ordner gefunden wird, ruft sich die Funktion einfach selbst auf, was sie rekursiv macht.
#!/bin/bash
[[ ! -d "$1" ]] && echo "Please point me at a directory!" && exit 1
function recursively_extract_all_rars_in() {
local x=`pwd` f
cd "$1"
for f in (*); do
[[ -d "$f" ]] && recursively_extract_all_rars_in "$f"
[[ -f "$f" ]] && [[ "$f" =~ "*.rar" ]] && unrar e "$f" && rm ${f%%.*}.r??
done
cd "$x"
}
recursively_extract_all_rars_in "$1"
Der Funktionsname ist völlig beliebig. Ich möchte, dass sie sich wie richtiges Englisch lesen, wenn sie mit ihren Argumenten aufgerufen werden. [[ -d /path ]]
Gibt „true“ zurück, wenn der Pfad existiert und ein Verzeichnis ist. -f
Macht das Entsprechende für Dateien. [[ "string" =~ "pattern"]]
ist ein Bashismus, der Mustervergleiche in Zeichenfolgen ermöglicht. Es funktioniert größtenteils genau wie Glob-Muster.
Die Zeile local x=pwd f
mag kryptisch sein, aber sie definiert lediglich zwei lokale Variablen: eine namens x, um das zu speichern pwd
, und eine namens f, nicht initialisiert (sie wird in der for-Schleife unten initialisiert, ich deklariere sie hier nur, damit sie lokal ist).
Das Speichern pwd
und Zurückkehren dazu, wenn Ihre Funktion es verwendet, cd
ist eine gute Sache (tm).
Bitte beachten Sie, dass die programmgesteuerte Verwendung der Ausgabe von ls
im Allgemeinen ein schlechtes Omen ist und Sie es wie die Pest zugunsten von vermeiden sollten find
.Wenn einer Ihrer Dateinamen ein Leerzeichen enthält, führt die Verwendung von „ls“ in Ihrem Skript zu großen Problemen.Du wurdest gewarnt.
ZSH
Ich bin nicht sicher, ob Sie dasselbe in Bash tun können, aber in ZSH würde ich das Folgende irgendwo einfügen.zshrc
function recursive_unrar() {
for f in **/*.rar; do
local cwd=`pwd` fbn=${f##*/}
cd "${f%/*}"
unrar e "$fbn"
rm "${fbn%%.*}.r{01..99} $fbn"
cd "$cwd"
done
}
Und rufen Sie es dann einfach aus dem entsprechenden Ordner heraus auf.