Come posso comprimere più file dalla riga di comando?


16

Perdona questa domanda basilare, ma non sono riuscito a trovare una risposta diretta o un semplice esempio sullo scambio di stack.

Diciamo che ho una cartella di file che vorrei comprimere in un file zip che posso condividere con i miei terribili amici di Windows (altrimenti userei tare finirò con esso). Sembra così:

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

Supponendo di aver zipinstallato:

sudo apt-get install zip

Vedo man zipche mi consente di utilizzare un elenco di file:

- @ elenchi di file. Se un elenco di file viene specificato come - @ [Non su MacOS], zip prende l'elenco dei file di input dall'input standard anziché dalla riga di comando. Per esempio,

          zip -@ foo

Quindi ho creato zip.lstche assomiglia a questo:

cat zip.lst

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

E ora ho provato:

zip -@ zip.lst

Ma non ha fatto altro che creare una riga vuota sulla console. E posso continuare a spingere Entere continua a creare più righe vuote senza eseguire il comando. Dopo alcune ricerche, mi sono reso conto che avevo bisogno di terminare l'input premendo Ctrl+D

Ma ora ho questo errore:

    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)

Che cosa!? In che modo il mio semplice elenco non è una "struttura di file valida"? Torna al manuale per ulteriori informazioni e guardo più da vicino:

Se un elenco di file è specificato come - @ ...

Quindi lo provo senza -@, e questo almeno lo elabora immediatamente senza dover premere Ctrl+ Dma mi rimane lo stesso errore .

Fortunatamente, ho trovato un commento su una risposta a una domanda quasi non correlata che mi ha portato a rendermi conto che dovevo nominare esplicitamente il file zip. Questo errore è dovuto al fatto che, per impostazione predefinita, stava tentando di creare un file zip chiamato zip.lst. Ma dato che questo è il nome del mio elenco, si potrebbe pensare che lo sovrascriverebbe semplicemente, ma no, in realtà stava cercando di aggiornarlo. E poiché l'elenco ovviamente non è un file zip, otteniamo l'errore di struttura del file non valido, e ora è chiaro il motivo per cui diceva "probabilmente non un file zip". Quindi ho provato:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Eureka! Vedo che il file zip è stato creato e la mia cartella ora contiene questo:

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

Ma aspetta prima di festeggiare, confermiamo prima il contenuto del file zip:

unzip -l files.zip

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

No! Bene, in realtà ha senso dall'uso standard perché ha appena compresso il file di un elenco che gli ho dato. Alla fine ho provato di nuovo con -@ma ho ottenuto lo stesso risultato.

Che cosa sto facendo di sbagliato?

A proposito, so che posso usare la GUI e farlo con il mio mouse, ma devo scriverlo, e in generale sono più veloce sulla CLI quando so cosa sto facendo.

Risposte:


23

Usa il <reindirizzamento dei file

zip files.zip -@ < zip.lst

Oppure potresti saltare l'elenco e solo glob

zip files.zip *.txt *.jpg

grazie steeldriver

Risposta storica

Sono contento che sia OK rispondere alla mia domanda perché volevo raccontare i miei disordini nella speranza che altri che seguivano nella mia scia di lacrime potessero essere risparmiati cercando alcune parole chiave.

Alla fine, ho scoperto la risposta giusta , ma è stata pubblicata la domanda sbagliata .

Un paio di punti di chiarezza:

  • Il manuale non si riferisce a un elenco letterale come in un file, ma piuttosto alla lista dei file sulla console.
  • È comprensibile che qualcuno possa essere indotto in errore a pensare che si fooriferisse all'elenco dei file, ma in realtà è destinato a rappresentare il nome del file zip di output.
  • L'elenco dei file viene omesso nell'esempio perché utilizza lo -@switch, il che dimostra che "prende l'elenco dei file di input dall'input standard anziché dalla riga di comando "

Comprendendo ciò, ora siamo armati di una varietà di modi per raggiungere l'obiettivo.

In primo luogo utilizzando l'elenco dei file che abbiamo creato, possiamo leggere l'elenco con cate reindirizzare l'output con una pipe come input standard a zip:

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%)

Vedere che adding: ...per ogni file è sicuramente un buon segno, ma abbiamo avuto le nostre speranze prima, quindi confermiamo:

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

DOLCE! Ma chi vuole comunque creare un elenco di utilizzo occasionale? È un modo terribile di risolvere questo particolare scenario. Sarebbe meglio ottenere un elenco da lse pipe che comprimere:

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%)

Favoloso! Ora creiamo filtri con la straordinaria potenza di grepcomprimere i jpg, ad esempio:

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

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

O solo i file che iniziano con "file"

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%)

5
Invece di utilizzare lse grepzip e di -@, è possibile utilizzare gocce di shell per selezionare i file direttamente sulla linea per esempio comando zip zip files.zip file*o zip images.zip *.jpg. Inoltre, quando si utilizza un elenco di nomi di file da un file, è possibile utilizzare il reindirizzamento invece di invocare un processo cat separato,zip files.zip -@ < zip.lst
steeldriver

Come puoi farlo funzionare con le directory nidificate insieme ai file?
BallpointBen

@BallpointBen userei findinvece dils
Jeff Puckett

6

il comando più semplice con livello di compressione massimo

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.