Comprimi tutti i file nella directory?


483

C'è un modo per comprimere tutti i file in una determinata directory con il zipcomando? Ho sentito parlare dell'uso *.*, ma voglio che funzioni anche per i file senza estensione.


2
Hai provato a navigare di livello superiore dalla directory desiderata e a farlo zip myarch.zip mydir/*?
Joseph R.,

13
o megliozip -r myarch.zip mydir/*
Adam

25
o megliozip -r myarch.zip mydir
ctrl-alt-delor

*.*indica qualsiasi file con un punto. In cp / m e dos tutti i file avevano un punto, e ti faceva scrivere (non si poteva fare *). Pertanto le persone sono venute a vedere *.*come tutti i file. Alla fine Microsoft ha aggiunto nomi di file lunghi che potrebbero avere zero o più punti. Per trovare un file con un punto su Windows devi digitare *.*.*.
ctrl-alt-delor,

Risposte:


705

Puoi semplicemente usare *; non ce n'è bisogno *.*. Le estensioni dei file non sono speciali su Unix. *corrisponde a zero o più caratteri, incluso un punto. Quindi corrisponde foo.png, perché sono zero o più caratteri (sette, per l'esattezza).

Nota che *per impostazione predefinita non corrisponde ai file che iniziano con un punto (né lo fa *.*). Questo è spesso quello che vuoi. In caso contrario, in bash, se shopt -s dotgloblo farai (ma escluderà comunque .e ..). Altre shell hanno diversi modi (o nessuna) per includere dotfile.

In alternativa, zipha anche -run'opzione (ricorsiva) per eseguire interi alberi di directory contemporaneamente (e non doversi preoccupare del problema dotfile):

zip -r myfiles.zip mydir

dove si mydirtrova la directory che contiene i tuoi file. Si noti che lo zip prodotto conterrà la struttura della directory e i file. Come sottolinea peterph nel suo commento, questo di solito è visto come una cosa positiva: l'estrazione dello zip memorizzerà ordinatamente tutti i file estratti in una sottodirectory.

Puoi anche dire a zip di non memorizzare i percorsi con l' opzione -j/ --junk-paths.

Il zipcomando viene fornito con la documentazione che ti dice di tutte le sue (molte) opzioni; digita man zipper vedere quella documentazione. Questo non è unico per zip; puoi ottenere la documentazione per la maggior parte dei comandi in questo modo.


9
Potresti voler aggiungere che è considerato una buona pratica contenere tutto nell'archivio in una directory di livello superiore, in modo tale da non inquinare la sua directory corrente durante l'estrazione.
peterph,

@peterph done. Anche se questa è meno una convenzione nei file zip che ad esempio nei tarfile, temo.
derobert,

Sfortunatamente sì. Probabilmente a causa dell'eredità di Windows del drag'n'drop sul desktop e dell'eredità di Linux di lavorare con i codici sorgente.
peterph,

2
Tieni presente che il *gorgogliamento della shell non include dotfile (ovvero nomi di file che iniziano con .). Questo è un altro vantaggio di comprimere l'intera directory per nome.
sig.

Ma usare -r include la directory stessa, che interrompe ciò che sto facendo. * Non include .e ..?
tkbx,

11

Nel mio caso volevo comprimere ogni file nel suo archivio, quindi ho fatto quanto segue (in zsh):

$ for file in *; do zip ${file%.*}.zip $file; done

1
Non c'è mkvqui? Anche qui nulla è particolarmente zshspecifico. Ti consigliamo di citare correttamente qualsiasi variabile contenente un nome file, quindi zip "${file%.*}.zip" "$file"con le doppie virgolette attorno a entrambe le variabili.
triplo il

1
@tripleee Innanzitutto, grazie per aver sottolineato il mio riferimento errato a mkv. In secondo luogo, la citazione degli argomenti non è necessaria in zsh, a differenza di bash. Ecco perché ho specificato che questo era un comando per zsh.
Radon Rosborough,

La sostituzione dell'ultimo punto e virgola con una e commerciale potrebbe velocizzarla significativamente (se il numero di file nella directory è ragionevole ...). Altrimenti find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'( -Pregolato in base ai thread della CPU ...) (Molte dipendenze GNU ...)
Gert van den Berg,

5

Un altro modo sarebbe usare find e xargs: (questo potrebbe includere una directory "." Nella zip, ma dovrebbe comunque estrarre correttamente. Con il mio test, zip ha rimosso il punto prima della compressione) find . -type f -exec zip zipfile.zip {} +

(Il +può essere sostituito con \;se la tua versione di findnon supporta la +fine di exec. Sarà comunque più lenta ...)

Questo includerà di default tutte le sottodirectory. Su GNU find -maxdepthpuò impedirlo.


(a differenza delle soluzioni che utilizzano *, questo includerà dotfile e non cadrà se ci sono troppi file in una directory)
Gert van den Berg

1

Un altro metodo (lento) per fare questo (che aggiunge un file alla zip alla volta):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

Questo ha i problemi di dotfile di *(soluzione alternativa aggiunta) e sarebbe avviare zip una volta per ogni file, aggiungendolo all'archivio. In bash, avrebbe a che fare con una grande quantità di file.

Sarebbe più lento della maggior parte degli altri metodi, ma è relativamente semplice.


1
Direi che questo è meno semplice della risposta accettata e più lento, il che pone la domanda: "Perché qualcuno dovrebbe farlo?". Se riesci a rispondere a questa domanda, ti consiglio di inserire quel contesto nella tua risposta, altrimenti penso che sia una cattiva risposta a una vecchia domanda che ha già una buona risposta.
Centimane,

@Centimane: noto i limiti. Sento che questo ha un valore educativo. (Se non saltare le directory, è abbastanza semplice). Se invece vuoi una risposta molto più veloce usando uno strumento (standard) esterno, la mia altra risposta lo copre . (con la gestione dei dotfile rimossi (che influisce sulla correttezza senza la loro assenza menzionata nella domanda), ritengo sia abbastanza elegante):for f in *; do zip zip.zip "$f"; done
Gert van den Berg

1
Nota che la risposta accettata non usa un comando esterno e sarebbe più veloce. In quale scenario sarebbe utile questa risposta?
Centimane,

@Centimane Con tar quando ci sono più file di quelli che bash può passare come parametri. (find + xargs sono migliori, perché i loop sono più facili ...). È una (unica) risposta alla domanda. Non è certamente la risposta ottimale. (Le risposte non ottimali possono ancora essere utili per problemi simili, se qualcuno ha una situazione leggermente diversa - ad esempio, se si desidera che il file tar contenga directory in esso)
Gert van den Berg,
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.