Entspricht dem "--strip-components = 1" von tar im entpacken?

22558
frigg

Ich habe ein Skript, das eine tar.gz-Datei in ein angegebenes Unterverzeichnis mysubfolder extrahiert :

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder; 

Gibt es eine gleichwertige Möglichkeit, dies mit einer zip-Datei zu tun?

41
Verwenden Sie einfach bsdtar drizzt vor 8 Jahren 2

2 Antworten auf die Frage

22
MestreLion

Wie Mathias sagte, unziphat 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 /foodas Chaos von Stripping /aund /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/foound /foo/bar/barsind 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 dotglobSie 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 ~/.bashrcoder ~/.profileund Sie müssen sich nie wieder darum kümmern. Einfach verwenden als:

unzip-strip sourcefile.zip mysubfolder 

(Beachten Sie, dass es automatisch mysubfolderfür Sie erstellt wird, wenn es nicht existiert.)

Dies wird nicht in eine vorhandene Verzeichnisstruktur entpackt, wie ich gehofft hatte (ich versuchte es anstelle von mysubfolder zu verwenden). Am Ende habe ich nur entpackt (zip-with-top-dir.zip entpacken) und dann kopiert (cp -rv -zip-top-zip-dir / *.). catgofire vor 7 Jahren 0
2
Mathias Bynens

Ich konnte eine solche Option in den Handbuchseiten nicht findenunzip, daher befürchte ich, dass dies unmöglich ist. :(

Sie könnten jedoch (je nach Situation) umgehen. Wenn Sie beispielsweise sicher sind, dass das einzige Verzeichnis der obersten Ebene in der ZIP-Datei einen Namen hat, foo-gefolgt von einer Versionsnummer, können Sie Folgendes tun:

cd /tmp unzip /path/to/file.zip cd foo-* cp -r . /path/to/destination/folder 
Schöner Ansatz, aber etwas unvollständig: Sie haben immer noch foo * dir mit dem gesamten extrahierten Inhalt. MestreLion vor 11 Jahren 0
Ja, ich habe nicht absichtlich "rm -rf foo- *" hinzugefügt, da dies potenziell gefährlich ist. Was wäre, wenn es bereits einen Ordner mit dem Namen "foo-bar" gab? Beachten Sie, dass die Extraktion im Ordner `/ tmp` durchgeführt wird, der ab und zu automatisch geleert wird. Mathias Bynens vor 11 Jahren 0
Deshalb habe ich Operationen mit "&&" verkettet: Ein bestimmter Schritt wird nur ausgeführt, wenn der vorherige Schritt erfolgreich war. Der letzte Schritt (der `rm ') wird nur ausgeführt, wenn * alle * Schritte ohne Fehler ausgeführt wurden. MestreLion vor 11 Jahren 0
Deswegen sollte man `` tmp / some-hardcoded-ordnername` 'niemals als temporären Ordner verwenden, sondern stattdessen `mktemp` verwenden. Dies garantiert, dass es keinen solchen Ordner gibt. Überprüfen Sie meine Antwort unten. MestreLion vor 11 Jahren 1
TIL über "mktemp". Vielen Dank! Mathias Bynens vor 11 Jahren 0