webentwicklung-frage-antwort-db.com.de

Wie entpacken Sie Archive in einem Verzeichnis und seinen Unterverzeichnissen rekursiv über die Unix-Befehlszeile?

Der Befehl unzip hat keine Option zum rekursiven Entpacken von Archiven.

Wenn ich folgende Verzeichnisstruktur und Archive habe:

/Mutter/Liebende.Zip 
/Skorbut/Seehunde.Zip 
/Skorbut/Heilmittel/Limes.Zip 

Und ich möchte alle Archive in Verzeichnisse mit demselben Namen wie jedes Archiv entpacken:

/Mutter/Lieben/1.txt 
/Mutter/Lieben.Zip 
/Skorbut/Seehunde/2.txt 
/Skorbut/Seehunde.Zip 
/Skorbut/Heilmittel/Limetten/3.txt 
/Skorbut/Heilmittel/Limetten.Zip 

Welchen Befehl oder welche Befehle würde ich ausgeben?

Es ist wichtig, dass dabei keine Dateinamen mit Leerzeichen blockiert werden.

56
chuckrector

Wenn Sie die Dateien in den entsprechenden Ordner extrahieren möchten, können Sie dies versuchen

find . -name "*.Zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;

Eine mehrfach verarbeitete Version für Systeme, die hohe E/A-Anforderungen erfüllen:

find . -name "*.Zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .Zip "fileName")" "fileName"'
89
Vivek Thomas

Hier ist eine Lösung, die den Befehl find und eine while-Schleife umfasst:

find . -name "*.Zip" | while read filename; do unzip -o -d "`basename -s .Zip "$filename"`" "$filename"; done;
32
chuckrector

Eine Lösung, die alle Dateinamen (einschließlich Zeilenumbrüche) korrekt verarbeitet und in ein Verzeichnis extrahiert, das sich am selben Speicherort wie die Datei befindet, nur mit der Erweiterung entfernt:

find . -name '*.Zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'

Beachten Sie, dass Sie problemlos mehr Dateitypen verarbeiten können (z. B. .jar) durch Hinzufügen mit -o, z.B.:

find . '(' -name '*.Zip' -o -name '*.jar' ')' -exec ...
16
robinst

Sie können find zusammen mit dem -exec-Flag in einer einzigen Befehlszeile verwenden, um den Job auszuführen

find . -name "*.Zip" -exec unzip {} \;
5
Jahangir

So etwas wie Gunzip mit der -r-Flagge? ....

Durchlaufen Sie die Verzeichnisstruktur rekursiv. Wenn es sich bei einem der in der Befehlszeile angegebenen Dateinamen um Verzeichnisse handelt, wird gzip in das Verzeichnis absteigen und alle dort gefundenen Dateien komprimieren (oder bei gunzip dekomprimieren).

http://www.computerhope.com/unix/gzip.htm

2
essexboyracer

Das funktioniert perfekt wie wir wollen:

Dateien entpacken:

find . -name "*.Zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'

Der obige Befehl erstellt keine doppelten Verzeichnisse.

Entfernen Sie alle Zip-Dateien:

find . -depth -name '*.Zip' -exec rm {} \;
1
Prabhav

Eine andere interessante Lösung wäre:

DESTINY=[Give the output that you intend]

# Don't forget to change from .Zip to .Zip.
# In my case the files were in .Zip.
# The echo were for debug purpose.

find . -name "*.Zip" | while read filename; do
ADDRESS=$filename
#echo "Address: $ADDRESS"
BASENAME=`basename $filename .Zip`
#echo "Basename: $BASENAME"
unzip -d "$DESTINY$BASENAME" "$ADDRESS";
done;
0
Prometheus

Wenn Sie cygwin verwenden, unterscheidet sich die Syntax für den Befehl basename geringfügig.

find . -name "*.Zip" | while read filename; do unzip -o -d "`basename "$filename" .Zip`" "$filename"; done;
0
Crutis

Mir ist klar, dass dies sehr alt ist, aber es war einer der ersten Zugriffe auf Google, als ich nach einer Lösung für etwas Ähnliches suchte. Deshalb werde ich hier posten, was ich getan habe. Mein Szenario ist ein wenig anders, da ich eigentlich nur ein Glas und alle darin enthaltenen Gläser vollständig explodieren lassen wollte. Deshalb habe ich die folgenden Bash-Funktionen geschrieben:

function explode {
    local target="$1"
    echo "Exploding $target."
    if [ -f "$target" ] ; then
        explodeFile "$target"
    Elif [ -d "$target" ] ; then
        while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(Zip|jar|ear|war|sar)")" != "" ] ; do
            find "$target" -type f -regextype posix-egrep -iregex ".*\.(Zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \;
        done
    else
        echo "Could not find $target."
    fi
}

function explodeFile {
    local target="$1"
    echo "Exploding file $target."
    mv "$target" "$target.tmp"
    unzip -q "$target.tmp" -d "$target"
    rm "$target.tmp"
}

Beachten Sie das <file-where-this-function-is-stored> wird benötigt, wenn Sie dies in einer Datei speichern, die für eine nicht interaktive Shell nicht so gelesen wird, wie ich es gerade tat. Wenn Sie die Funktionen in einer Datei speichern, die auf nicht interaktiven Shells geladen ist (z. B. .bashrc Ich glaube) du kannst die ganze source Anweisung fallen lassen. Hoffentlich hilft das jemandem.

Eine kleine Warnung - explodeFile löscht auch die komprimierte Datei. Sie können dies natürlich ändern, indem Sie die letzte Zeile auskommentieren.

0
Thor84no