Wie entpacken Sie rekursiv Archive in einem Verzeichnis und dessen Unterverzeichnissen aus der Unix-Kommandozeile?
Frage
Der unzip
Befehl nicht eine Option für die Archive rekursiv unzipping.
Wenn ich die folgende Verzeichnisstruktur und Archive:
/Mother/Loving.zip /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes.zip
Und ich möchte alle der Archive in Verzeichnisse mit dem gleichen Namen wie jedes Archiv entpacken:
/Mother/Loving/1.txt /Mother/Loving.zip /Scurvy/Sea Dogs/2.txt /Scurvy/Sea Dogs.zip /Scurvy/Cures/Limes/3.txt /Scurvy/Cures/Limes.zip
Welcher Befehl oder Befehle würde ich ausgeben?
Es ist wichtig, dass dies nicht auf Dateinamen nicht ersticken, die Leerzeichen in ihnen haben.
Lösung
Wenn Sie die Dateien in den entsprechenden Ordner extrahieren möchten Sie versuchen, diese können
find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;
Eine Mehr verarbeitete Version für Systeme, die hohe E / A verarbeiten kann:
find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"'
Andere Tipps
Hier ist eine Lösung, die den Befehl find und eine while-Schleife beinhaltet:
find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;
Eine Lösung, die alle Dateinamen (einschließlich Zeilenumbrüche) korrekt behandelt und extrahiert in ein Verzeichnis, das an der gleichen Stelle wie die Datei ist, nur mit der Erweiterung entfernt:
find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';'
Beachten Sie, dass Sie leicht es mehr Dateitypen (wie .jar
) mit ihnen umgehen, indem das Hinzufügen -o
verwenden, z.
find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ...
Sie nutzen könnten zusammen mit dem exec-Flag in einer einzigen Befehlszeile finden die Arbeit zu tun
find . -name "*.zip" -exec unzip {} \;
So etwas wie gunzip der -r Flag verwendet? ....
rekursiv die Verzeichnisstruktur Reisen. Wenn eine der Dateinamen in der Befehlszeile angegebenen Verzeichnisse sind, werden gzip in das Verzeichnis absteigen und komprimieren Sie alle Dateien, die dort gefunden (oder sie im Fall von gunzip dekomprimieren).
Das funktioniert perfekt, wie wir wollen:
Dekomprimieren von Dateien:
find . -name "*.zip" | xargs -P 5 -I FILENAME sh -c 'unzip -o -d "$(dirname "FILENAME")" "FILENAME"'
Vor Befehl erstellt keine doppelten Verzeichnisse.
alle ZIP-Dateien entfernen:
find . -depth -name '*.zip' -exec rm {} \;
Wenn Sie Cygwin verwenden, die Syntax ist etwas anders für den Basisnamen Befehl.
find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;
Ich weiß, das ist sehr alt, aber es war unter den ersten Treffer bei Google, wenn ich nach einer Lösung zu suchen etwas ähnlich, also werde ich schreiben, was ich hier tat. Mein Szenario ist etwas anders als ich im Grunde wollte nur voll ein Glas zu explodieren, zusammen mit allen Gläsern in sie enthalten, also schrieb ich folgende bash Funktionen:
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 den <file-where-this-function-is-stored>
, die benötigt wird, wenn Sie diese in einer Datei sind zu speichern, die nicht für ein nicht-interaktiv Shell gelesen wird, als ich zufällig sein. Wenn Sie die Funktionen in einer Datei sind die Speicherung geladen auf nicht-interaktiven Shells (zum Beispiel .bashrc
glaube ich) können Sie die gesamte source
Anweisung löschen. Hoffentlich wird dies jemand helfen.
Eine kleine Warnung - explodeFile
löscht auch die geZIPten Datei, können Sie sich natürlich ändern, dass durch Kommentare, die letzte Zeile aus
Eine weitere 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;