Datei entpacken, welches Verzeichnis wurde erstellt?

7

Zielsetzung:

Weisen Sie nach dem Erweitern des Archivs a.zipmit dem Befehl unzipon Ubuntu 12.10den Namen des Ordners a.zipzu, auf den die bashVariable erweitert wurde v.

a.zip Es wird davon ausgegangen, dass die Erweiterung auf einen einzelnen Ordner und nicht auf mehrere Ordner erfolgt.

Beispiel:

Wenn unzip a.zipin Ordner erweitert ./foo/, echo $vsollte zurückkehren foo.

Meine Umgebung:

GNU/Linux (kernel 3.5.0-25-generic)
Ubuntu 12.10    
bash v4.2.37(1)-release
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

Aktuelle Problemumgehung Ich bin unzufrieden mit: Erweitern über gibt unzip -d bar a.zipdann v=$(ls -1 bar)das richtige Ergebnis, bringt aber das Dateisystem durcheinander.

Robottinosino
quelle

Antworten:

4

Bitte schön:

v=$(unzip a.zip | grep -m1 'creating:' | cut -d' ' -f5-)

Erläuterung

  • $(...)ist eine Capture-Shell. Es erfasst die Ausgabe der darin enthaltenen Befehle und ersetzt sie wie eine Variable.
  • Die Ausgabe des unzipBefehls wird an weitergeleitet grep, wobei das Argument übergeben wird -m1, damit nur das erste Ergebnis und der Text creating:, der Teil des Textes ist unzip, beim Erstellen eines Verzeichnisses an stdout zurückgegeben werden. grepDruckt creating: foo/auf stdout, das weitergeleitet wird cut.
  • cutwird verwendet, um alle Spalten (durch Leerzeichen getrennt) nach der zweiten zu drucken. Wir geben jedoch von 5 bis zum Ende der Zeile an, da dem Wort creating:einige Leerzeichen vorangestellt sind. Wir möchten alle Spalten bis zum Ende der Zeile verwenden, falls der Verzeichnisname Leerzeichen enthält. Die endgültige Ausgabe ist foo/.

quelle
Vielen Dank! :) Ich mag das -m1auf grepund ich wusste nicht , cutüber bis zum Ende Druck -fN-(letzte Feldnummer weggelassen). Du hast mir etwas beigebracht! Dafür -> upvote! Haben Sie nicht nur ein Tool verwendet (z. B. awk), weil 1. grepund cutweiter verbreitet sind als awkund 2. Sie finden, was Sie geschrieben haben, "lesbarer"? Ich würde gerne Ihre Begründung hören, da man einen Einzeiler wie folgt zusammenstellen könnte : stackoverflow.com/questions/15776352 PS: Sie brauchen keine Anführungszeichen, keine Wortaufteilung in Bash zur variablen Zuweisungszeit. v=$(echo a b)ist das gleiche wiev="$(echo a b)"
Robottinosino
Es ist einfacher, alle Felder bis zum Ende der Zeile mit auszuwählen, cutals mit awk. Es ist meiner Meinung nach auch etwas lesbarer. Dieser Einzeiler ist interessant. Ich muss mehr darüber lesen awk. Die Verwendung von Anführungszeichen in Variablenzuweisungen ist eine schlechte Angewohnheit von mir, die sich aus einem Texteditor ergibt, der den Text in Anführungszeichen schön gefärbt hat. Außerdem ist meine Standardsprache C.
1
Dies ist ein wirklich guter Tipp, aber es scheint, dass das Abrufen des Ausgabeordners auf diese Weise den Entpackungsprozess irgendwie unterbricht. Gibt es eine Möglichkeit, das Ausgabeverzeichnis abzurufen, ohne den Entpackungsprozess zu unterbrechen?
Marcin Bobowski
2
  • Sie können unzip -lden Inhalt des Archivs auflisten und die Ausgabe analysieren
  • Oder Sie können das Verzeichnis auflisten, das Archiv extrahieren, das das Verzeichnis erneut auflistet, und die beiden Auflistungen mit vergleichen diff
Bonsi Scott
quelle
Evans Lösung ist direkter: Extrahiert und analysiert den Namen des Verzeichnisses. (Obwohl Ihre Idee gut ist und die Grundlage für Evans Lösung. Dafür - ich stimme mit Dank zu.)
Robottinosino
1

Das AVFS- Dateisystem bietet eine Ansicht des Dateisystems, in der auf jede Archivdatei /path/to/foo.zipals Verzeichnis zugegriffen werden kann~/.avfs/path/to/foo.zip# .

mountavfs
ls ~/.avfs$PWD/foo.zip\#

Wenn dieser lsBefehl ein einzelnes Verzeichnis anzeigt, wird beim Entpacken der Zip-Datei dieses Verzeichnis und darunter liegende Dateien erstellt. Beachten Sie, dass eine Zip-Datei möglicherweise auf diese Weise organisiert ist oder nicht.

Hier ist ein Ausschnitt, der Ihre Annahme überprüft und dirgegebenenfalls den Verzeichnisnamen festlegt . Warnung: Wenn die Zip-Datei Dateien enthält, deren Name mit einem .(Punktdateien) beginnt , werden sie ignoriert.

zip_directory_name () {
  case $1 in
    /*) ;;
    *) set "$PWD/$1";;
  esac
  cd ~/.avfs${1}\# || exit 2
  set -- *
  if [ $# -eq 1 ] && [ -d "$1" ]; then
    printf %s "$1"
  else
    return 1 # more than one top-level file, or a single non-directory
  fi
}
dir=$(zip_directory_name foo.zip) || exit $?
Gilles 'SO - hör auf böse zu sein'
quelle
1

Seien Sie mit Ihrer Problemumgehung unzufrieden, wenn Sie möchten, aber es ist tatsächlich die richtige Lösung.

d="`mktemp -d`"
unzip -d "$d" "$zipfile"
v="`basename "$d"/*`"
mv "$d"/"$v" "$v"
rmdir "$d"
echo "$v"

Dies ist ausführlich, aber - solange es wirklich nur ein Verzeichnis in der Zip-Datei gibt, das Sie wahrscheinlich zuerst überprüfen sollten - ist es zuverlässig.

lsund grepist weniger zuverlässig, da es davon abhängt, wie die Ausgabe aussieht. In einem anderen Gebietsschema ist möglicherweise keine Zeichenfolge "create:" vorhanden. In der nächsten Version von unzip kann es aus beliebigen Gründen geändert werden.

Frostschutz
quelle