Wie kann ich mehrere Dateien in der Befehlszeile komprimieren?

16

Verzeihen Sie diese grundlegende Frage, aber ich konnte keine direkte Antwort oder ein einfaches Beispiel für den Stapelaustausch finden.

Nehmen wir an, ich habe einen Ordner mit Dateien, die ich in eine ZIP-Datei komprimieren möchte, die ich mit meinen schrecklichen Windows-Freunden teilen kann (ansonsten würde ich ihn nur verwenden tarund damit fertig sein). Es sieht aus wie das:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
└── test.jpg

Angenommen, ich habe zipinstalliert:

sudo apt-get install zip

Ich sehe daraus, man zipdass es mir erlaubt, eine Dateiliste zu verwenden:

- @ Dateilisten. Wenn eine Dateiliste als - @ [Nicht unter MacOS] angegeben ist, übernimmt zip die Liste der Eingabedateien von der Standardeingabe anstelle von der Befehlszeile. Beispielsweise,

          zip -@ foo

Also habe ich folgendes erstellt zip.lst:

cat zip.lst

file1.txt
file2.txt
file3.txt
file.jpg
test.jpg

Und jetzt habe ich versucht:

zip -@ zip.lst

Aber es hat nichts anderes getan, als eine leere Zeile auf der Konsole zu erstellen. Und ich kann weiter pushen Enterund es werden immer mehr Leerzeilen gemacht, ohne dass der Befehl scheinbar ausgeführt wird. Nach einigem Suchen wurde mir klar, dass ich die Eingabe durch Drücken von Ctrl+ beenden mussteD

Aber jetzt bekomme ich diesen Fehler:

    zip warning: missing end signature--probably not a zip file (did you
    zip warning: remember to use binary mode when you transferred it?)
    zip warning: (if you are trying to read a damaged archive try -F)

zip error: Zip file structure invalid (zip.lst)

Was!? Wie ist meine einfache Liste keine "gültige Dateistruktur"? Zurück zum Handbuch, um weitere Informationen zu erhalten, und ich sehe mir Folgendes genauer an:

Wenn eine Dateiliste als - @ ... angegeben ist

Also versuche ich es ohne -@, und das verarbeitet es zumindest sofort, ohne Ctrl+ drücken zu müssen, Daber ich habe den gleichen Fehler .

Glücklicherweise fand ich einen Kommentar zu einer Antwort auf eine fast unabhängige Frage, bei der mir klar wurde, dass ich die Zip-Datei explizit benennen musste. Dieser Fehler ist darauf zurückzuführen, dass standardmäßig versucht wurde, eine ZIP-Datei mit dem Namen zu erstellen zip.lst. Aber da dies der Name meiner Liste ist, könnte man meinen, sie würde einfach überschrieben, aber nein, es wurde tatsächlich versucht, sie zu aktualisieren. Und da die Liste offensichtlich keine Zip-Datei ist, erhalten wir den ungültigen Dateistrukturfehler, und jetzt ist klar, warum dort "wahrscheinlich keine Zip-Datei" steht. Also habe ich versucht:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Eureka! Ich kann sehen, dass die Zip-Datei erstellt wurde und mein Ordner jetzt Folgendes enthält:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
├── files.zip
├── test.jpg
└── zip.lst

Aber warten Sie, bevor wir feiern, lassen Sie uns zuerst den Inhalt der ZIP-Datei bestätigen:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       48  2016-05-24 15:30   zip.lst
---------                     -------
       48                     1 file

Nein! Nun, eigentlich macht das Sinn, weil es nur die eine Listendatei gezippt hat, die ich ihm gegeben habe. Schließlich habe ich es noch einmal versucht, -@aber das gleiche Ergebnis erzielt.

Was mache ich falsch?

Übrigens, ich weiß, dass ich die GUI verwenden und mit meiner Maus ausführen kann, aber ich muss dies skripten, und im Allgemeinen bin ich auf der CLI schneller, wenn ich weiß, was ich tue.

Jeff Puckett
quelle

Antworten:

23

Verwenden Sie die <Dateiumleitung

zip files.zip -@ < zip.lst

Oder Sie könnten die Liste überspringen und nur glob

zip files.zip *.txt *.jpg

danke steeldriver

Historische Antwort

Ich bin froh , dass es in Ordnung ist, meine eigene Frage zu beantworten, weil ich meinen Aufruhr in der Hoffnung aufzeichnen wollte, dass andere, die meinen Tränen folgen, durch die Suche nach Schlüsselwörtern verschont bleiben könnten.

Irgendwann habe ich die richtige Antwort gefunden , aber sie wurde auf die falsche Frage gestellt .

Ein paar Punkte der Klarheit:

  • Das Handbuch bezieht sich nicht auf eine Literalliste wie in einer Datei, sondern wörtlich auf das Auflisten der Dateien auf der Konsole.
  • Es ist verständlich, dass jemand in die Irre geführt foowird und den Namen der Ausgabe-Zip-Datei ansieht.
  • Die Liste der Dateien wird in dem Beispiel weggelassen, da der -@Schalter verwendet wird, um zu demonstrieren, dass "die Liste der Eingabedateien von der Standardeingabe anstatt von der Befehlszeile übernommen wird ".

Nachdem wir dies verstanden haben, stehen uns jetzt verschiedene Möglichkeiten zur Verfügung, um das Ziel zu erreichen.

Zuerst können wir mit der von uns erstellten Dateiliste die Liste auslesen catund die Ausgabe mit einer Pipe als Standardeingabe an zip umleiten:

cat zip.lst | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Das adding: ...für jede Datei zu sehen, ist sicherlich ein gutes Zeichen, aber wir hatten schon vorher unsere Hoffnungen, also lassen Sie uns einfach bestätigen:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2016-05-24 14:54   file1.txt
        0  2016-05-24 14:54   file2.txt
        0  2016-05-24 14:54   file3.txt
        0  2016-05-24 15:00   file.jpg
        0  2016-05-24 14:59   test.jpg
---------                     -------
        0                     5 files

SÜSS! Aber wer möchte schon eine Liste zur einmaligen Verwendung erstellen? Das ist eine schreckliche Art und Weise, dieses spezielle Szenario zu lösen. Es wäre besser, eine Liste von zu bekommen lsund diese zu zip umzuleiten:

ls | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Fabelhaft! Jetzt erstellen wir Filter mit der unglaublichen Kraft, grepzum Beispiel nur die JPGs zu komprimieren:

ls | grep .jpg | zip -@ images.zip

  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Oder nur Dateien, die mit "file" beginnen

ls | grep file. | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
Jeff Puckett
quelle
5
Anstelle von lsund grepund zip -@können Sie auch Shell-Globs verwenden, um Dateien direkt in der zip-Befehlszeile auszuwählen, z . B. zip files.zip file*oder zip images.zip *.jpg. Auch wenn eine Liste von Dateinamen aus einer Datei verwenden, können Sie die Umleitung verwenden , anstatt eine separate Katze Prozess des Aufrufens,zip files.zip -@ < zip.lst
steeldriver
Wie können Sie diese Funktion mit verschachtelten Verzeichnissen neben Dateien ausführen?
BallpointBen
@BallpointBen Ich würde findanstelle von verwendenls
Jeff Puckett
6

der einfachste Befehl mit maximaler Komprimierungsstufe

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Ansyori
quelle