Verzeichnis erstellen, wenn das Zip-Archiv mehrere Dateien enthält

8

Wenn ein Archiv mehrere Dateien im Stammverzeichnis enthält, möchte ich ein Verzeichnis erstellen, das nach dem Dateinamen benannt ist (ohne Erweiterung). Wenn ein Archiv nur ein Verzeichnis enthält, möchte ich es einfach extrahieren. Angenommen, ich habe das folgende Archiv:

# file: withdir.zip
somedir/alpha
somedir/beta
somedir/gamma

Wenn ich es im aktuellen Verzeichnis extrahiere, möchte ich es einfach extrahieren lassen ( unzip withdir.zip):

somedir/alpha
somedir/beta
somedir/gamma

Nehmen wir nun folgendes Archiv an:

# file: nodir.zip
alpha
beta
gamma

Wenn ich unzip nodir.zipstarte, überfalle ich das aktuelle Verzeichnis mit den drei Dateien:

alpha
beta
gamma

Ich würde lieber rennen unzip -d nodir nodir.zip:

nodir/alpha
nodir/beta
nodir/gamma

Wenn ich Nautilus benutze und mit der rechten Maustaste auf "Hier extrahieren" klicke. Es verhält sich genau so, wie es sollte. Aber leider finde ich habe nicht eine Befehlszeilenoption für unzipoder 7zwas ergibt das gleiche Verhalten. Wie erreicht man das? Gibt es andere Tools, die ich stattdessen verwenden kann (keine GUI)?

Marco
quelle

Antworten:

7

Ich würde so etwas machen (zsh-Syntax):

unz() (
  tmp=$(TMPDIR=. mktemp -d -- ${${argv[-1]:t:r}%.tar}.XXXXXX) || exit
  print -r >&2 "Extracting in $tmp"
  cd -- $tmp || exit
  [[ $argv[-1] = /* ]] || argv[-1]=../$argv[-1]
  (set -x; "$@"); ret=$?
  files=(*(ND[1,2]))
  case $#files in
    (0) print -r >&2 "No file created"
        rmdir -v "../$tmp";;
    (1) mv -v -- $files .. && rmdir -v ../$tmp;;
    (*) mv -vT ../$tmp ../$tmp:r;;
  esac && exit $ret
)

Das ist:

  1. Erstellen Sie auf jeden Fall ein Verzeichnis
  2. Führen Sie den Befehl aus
  3. abhängig davon, wie viele Dateien der Befehl generiert hat:
    • Entfernen Sie dieses Verzeichnis (falls keine Datei erstellt wurde).
    • Wenn nur eine Datei / ein Verzeichnis erstellt wurde, verschieben Sie diese um eine Ebene nach oben und verwerfen Sie unser Verzeichnis
    • Andernfalls versuchen Sie, die zufällige Zeichenfolge vom Ende unseres temporären Verzeichnisses zu entfernen.

Auf diese Weise können Sie Folgendes tun:

unz unzip foo.zip
unz tar xf foo.tar.gz

Es wird davon ausgegangen, dass das letzte Argument für den Extraktionsbefehl die zu extrahierende Datei ist. Es werden auch GNU-Tools für die -vOptionen vorausgesetzt . Auf Nicht-GNU-Systemen können Sie diese entfernen und möglicherweise die Protokollierung von Hand durchführen. mv -Tist auch GNU-spezifisch und soll erzwingen mv, nur eine Umbenennung durchzuführen.

Stéphane Chazelas
quelle
3

Wie unzipund 7zsowohl einen Schalter für die Ausgabe auf ein bestimmtes Verzeichnis hat, können Sie ein einfaches Skript, das überprüft , erstellen, wie viele Dateien in der Wurzel des Archivs sind und fügen dann den Schalter , wenn nötig.

Mit 7z ist dies einfacher, da es über einen -sltSchalter verfügt, der die Ausgabe maschinenlesbarer macht. Für jede Datei in der Zip-Datei enthält die Ausgabe eine Path = ...Zeile. Dateien im Stammverzeichnis sollten keine /im Wert enthalten.

Ein einfaches Skript, das ich geschrieben habe, um Dateien auf diese Weise zu entpacken:

#!/bin/sh
for archive in "$@"; do
    # count files in root dir
    rootfiles=$(7z l -slt "${archive}" | grep -c 'Path = [^/]*$')

    # add -o switch, if more than one file in root
    # checks for >2, because path of the zip file itself is listed too
    if [ $rootfiles -gt 2 ]; then
        filename=${archive##*/}
        rootname=${filename%.*}
        opt="-o${rootname}"
    fi

    #unpack
    7z x "${opt}" "${archive}"
done

Bearbeiten: Skript funktioniert jetzt auch mit Zip

crater2150
quelle
Dieses Skript funktioniert nicht wie erwartet. Es erstellt ein Verzeichnis withdirfür das Archiv, withdir.zipobwohl es nur ein Verzeichnis im Stammverzeichnis enthält, da es grep -c "Folder = -"zurückgibt 3.
Marco
ah, Ordner scheint für Zip-Dateien anders zu sein. Ich werde nach einem Fix suchen
crater2150
@ Marco: Ich habe das Skript geändert und es mit Zip-Dateien getestet. Es erstellt den Ordner jetzt nur bei Bedarf
crater2150
3

patool verarbeitet verschiedene Arten von Archiven und erstellt ein Unterverzeichnis, falls das Archiv mehrere Dateien enthält, um zu verhindern, dass das Arbeitsverzeichnis mit den extrahierten Dateien überfüllt ist .

Archiv erstellen

patool create archive.zip somedirectory

Archiv extrahieren

patool extract archive.zip

Verwenden Sie, um eine Liste der unterstützten Formate zu erhalten patool formats.

Marco
quelle
1

Sie können auch unar verwenden , wodurch standardmäßig ein Verzeichnis erstellt wird, wenn zwei oder mehr Dateien der obersten Ebene vorhanden sind:

$ touch 1 2
$ zip a.zip 1 2
  adding: 1 (stored 0%)
  adding: 2 (stored 0%)
$ unzip -l a.zip
Archive:  a.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  04-29-14 10:56   1
        0  04-29-14 10:56   2
 --------                   -------
        0                   2 files
$ unar a.zip
a.zip: Zip
  1  (0 B)... OK.
  2  (0 B)... OK.
Successfully extracted to "a".
$ ls a
1 2

Hinzufügen, -dum immer ein enthaltenes Verzeichnis zu erstellen.

Lri
quelle