Wie Mathias sagte, unzip
gibt es keine solche Option, aber ein einzeiliges Bash-Skript kann den Job erledigen.
Das Problem ist: Der beste Ansatz hängt von Ihrem Archivlayout ab. Eine Lösung , die übernimmt ein einziges Top-Level - dir kläglich scheitert , wenn der Inhalt direkt in das Archiv Wurzel ist (man denke etwa /a/foo
/b/foo
/foo
und das Chaos der Stripping /a
und /b
).
Und das gleiche Scheitern passiert mit tar --strip-component
. Es gibt keine Einheitslösung.
Also, um das Wurzelverzeichnis zu entfernen, vorausgesetzt, es gibt eins (und nur eins):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
Stellen Sie einfach sicher, dass Dateien / Verzeichnisse der zweiten Ebene nicht den gleichen Namen wie die übergeordneten Dateien der obersten Ebene haben (z. B. /foo/foo
). Aber /foo/bar/foo
und /foo/bar/bar
sind ok Wenn dies der Fall ist oder Sie nur auf Nummer sicher gehen möchten, können Sie ein temporäres Verzeichnis zum Extrahieren 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:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
Apropos Bash, Sie sollten es aktivieren dotglob
, um versteckte Dateien einzuschließen, und Sie können alles in einer einzigen, praktischen Funktion zusammenfassen:
unzip-strip() (
local zip=$1
local dest=${2:-.}
local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
shopt -s dotglob && local f=("$temp"/*) &&
if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
mv "$temp"/*/* "$dest"
else
mv "$temp"/* "$dest"
fi && rmdir "$temp"/* "$temp"
)
Geben Sie das jetzt in Ihr ~/.bashrc
oder ein, ~/.profile
und Sie müssen sich nie wieder darum kümmern. Verwenden Sie einfach als:
unzip-strip sourcefile.zip mysubfolder
(Beachten Sie, dass es automatisch mysubfolder
für Sie erstellt wird, wenn es nicht existiert.)