Wie Mathias sagte, unzip
hat keine solche Option, aber ein einzeiliges Bash-Skript kann die Arbeit erledigen.
Das Problem ist: Der beste Ansatz hängt von Ihrem Archivlayout ab. Eine Lösung, die ein einzelnes Verzeichnis der obersten Ebene voraussetzt, schlägt fehl, wenn sich der Inhalt direkt im Archivstammverzeichnis befindet (denken Sie über /a/foo
/b/foo
/foo
das Chaos von Stripping /a
und /b
).
Und das Gleiche passiert mit tar --strip-component
. Es gibt keine einheitliche Lösung.
Um das Root-Verzeichnis zu entfernen, vorausgesetzt, es gibt einen (und nur einen):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "$"
Stellen Sie einfach sicher, dass Dateien / Verzeichnisse der zweiten Ebene nicht denselben Namen wie die der obersten Ebene haben (z. B. /foo/foo
). Aber /foo/bar/foo
und /foo/bar/bar
sind in Ordnung. Wenn dies der Fall ist oder Sie einfach nur sicher sein möchten, können Sie ein temporäres Verzeichnis für die Extraktion verwenden:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" && mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
Wenn Sie Bash verwenden, können Sie testen, ob die oberste Ebene ein einzelnes Verzeichnis ist oder nicht verwendet wird:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "$" ]] && echo "Single dir!"
Wenn Sie von Bash sprechen, sollten dotglob
Sie diese Option aktivieren, um versteckte Dateien einzuschließen, und Sie können alles in einer einzigen, praktischen Funktion zusammenfassen:
unzip-strip() ( local zip=$1 local dest=$ local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" && shopt -s dotglob && local f=("$temp"/*) && if (( ${#f[@]} == 1 )) && [[ -d "$" ]] ; then mv "$temp"/*/* "$dest" else mv "$temp"/* "$dest" fi && rmdir "$temp"/* "$temp" )
Jetzt legen Sie das in Ihre ~/.bashrc
oder ~/.profile
und Sie müssen sich nie wieder darum kümmern. Einfach verwenden als:
unzip-strip sourcefile.zip mysubfolder
(Beachten Sie, dass es automatisch mysubfolder
für Sie erstellt wird, wenn es nicht existiert.)