Puoi usare globstar.
Con l' globstar
opzione shell abilitata, tutto ciò che serve è gzip -vk **/*.{css,html}
.
La shell Bash ha globstar
un'opzione che ti consente di scrivere globi ricorsivi con **
. shopt -s globstar
lo abilita. Ma potresti non voler farlo per altri comandi che esegui in seguito, quindi puoi eseguirlo e il tuo gzip
comando in una subshell .
Questo comando gzip
è tutto .css
e .html
file nella directory corrente una delle sue sottodirectory, una qualsiasi delle loro sottodirectory, ecc., Mantenendo i file originali ( -k
) e raccontandoti cosa sta facendo ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Se si desidera abbinare i nomi dei file senza distinzione tra maiuscole e minuscole in modo da includere quelle estensioni con alcune o tutte le lettere maiuscole, è possibile anche abilitare l' nocaseglob
opzione shell:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
separa i due comandi e l'esterno fa (
)
sì che vengano eseguiti in una subshell. L'impostazione di un'opzione shell in una subshell non comporta l'impostazione nella shell chiamante. Se non desidera abilitare globstar
allora si può eseguire shopt -s globstar
; quindi puoi semplicemente eseguire il comando:
gzip -vk **/*.{css,html}
Puoi disabilitare globstar
con shopt -u globstar
. Puoi verificare se è attualmente abilitato con shopt globstar
.
Come funziona
La chiave per il funzionamento di questo gzip
comando è che la shell esegue espansioni su di esso per produrre un elenco di ciascun file nella gerarchia di directory con un nome corrispondente, quindi passa ciascuno di questi nomi di file come argomenti a gzip
.
- L'espansione del controvento si trasforma
**/*.{css,html}
in **/*.css **/*.html
.
- Quindi il globbing espande questi due modelli nei nomi dei file accessibili nella directory corrente (
**
, a causa di globstar
) i cui nomi di file sono costituiti da qualcosa ( *
) seguito dal suffisso specificato ( .css
o .html
in questo caso).
Questo non corrisponde ai file i cui nomi iniziano con.
o quelli che risiedono nelle directory denominate in questo modo. Probabilmente non hai tali file HTML e CSS e, se lo fai, probabilmente non vuoi includerli. Ma se vuoi includerli, puoi abbinarli esplicitamente a seconda delle tue esigenze. Ad esempio, il passaggio **/*.{css,html}
a **/{,.}*.{css,html}
include i file che iniziano con .
mentre non si cerca ancora nelle cartelle che lo fanno.
Se vuoi che siano inclusi sia i file i cui nomi iniziano .
che i file nelle directory i cui nomi iniziano con .
, c'è un modo più semplice e pulito: abilita l' dotglob
opzione shell.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
O se si desidera la corrispondenza senza distinzione tra maiuscole e minuscole e la corrispondenza dei nomi di file che iniziano con .
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
È possibile, sebbene molto raro, **
espandersi a qualcosa di troppo lungo.
Se si dispone di un numero enorme di file denominati in questo modo, ciò potrebbe non riuscire con un messaggio di errore che spiega che la shell non può costruire la riga di comando perché sarebbe troppo lunga. (Anche con migliaia di file, questo di solito non è un problema.)
gzip
non verrà chiamato affatto, quindi non otterrai un lavoro a metà.
Se si verifica questo errore, o se sei preoccupato, puoi usarlo find
con -exec
, come descrive steeldriver (con {} \;
) o come descrivo di seguito (con {} +
).
È possibile utilizzare find
con l' -exec
azione e +
per l'efficienza.
Il gzip
comando supporta l'assegnazione di nomi di più file da comprimere. Ma questo find
comando, sebbene funzioni bene e non sarà lento a meno che tu non abbia molti file, esegue il gzip
comando una volta per ogni file:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Funziona e puoi sicuramente usarlo. ( .
cerca dalla directory corrente. Oltre a questo, è davvero un modo leggermente diverso di scrivere il comando nella risposta molto buona di steeldriver ; puoi usare qualunque stile tu preferisca.)
Puoi anche far find
passare più nomi di file gzip
ed eseguirlo solo tutte le volte necessarie, il che è quasi sempre solo una volta. Per farlo, usa +
invece di\;
. L' +
argomento dovrebbe venire subito dopo {}
. find
sostituisce +
con eventuali nomi di file aggiuntivi.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Va bene usare +
anche se ci sono solo pochi file corrispondenti e, quando ce ne sono molti, può essere notevolmente più veloce di avere una gzip
chiamata separata per ogni file.
Come menziona steeldriver , è possibile utilizzare -iname
invece di -name
abbinare i file il cui nome termina come .css
o .html
ma con lettere maiuscole diverse. Ciò corrisponde all'abilitazione nocaseglob
nel globstar
metodo basato su sopra descritto.
Infine, probabilmente non hai file o directory corrispondenti che iniziano con .
. Ma se lo fai, find
li include automaticamente. Se si desidera escluderli (come accade con il globstar
metodo basato su dettagliato sopra quando dotglob
è disattivato), è possibile :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Il globstar
modo basato sopra descritto è più semplice da scrivere, soprattutto se si escludono directory e file che iniziano con .
, poiché questo è il valore predefinito.
Cosa non fare ...
I nomi di file possono contenere qualsiasi carattere tranne il separatore di percorso /
e il carattere null . Esistono molte tecniche che si rompono su nomi di file strani e di solito sono più complicate delle tecniche che funzionano sempre. Quindi suggerisco di evitarli anche quando sai (o pensi di sapere) che stanno bene nella tua situazione specifica. E ovviamente non devi usarli se potresti avere nomi di file con caratteri che possono essere trattati in modo speciale, compresi gli spazi.
È possibile reindirizzare in modo sicuro l'output di find
un altro comando che lo elabora se si utilizza -print0
o un'azione simile per indurlo a posizionare un carattere null tra i percorsi anziché una nuova riga e non altrimenti. I nomi dei file possono contenere newline (anche se ti scoraggio dal nominare deliberatamente i file con loro). Un find
comando con l' -print
azione - incluso il comando find senza azione esplicita, poiché da allora -print
è l'impostazione predefinita - non produce output che può essere convogliato in sicurezza o altrimenti fornito a un altro comando che esegue un'azione sui file.
L'output find
prodotto con l' -print0
azione può essere tranquillamente reindirizzato xargs -0
(il -0
flag indica xargs
di prevedere un input separato da null).
-r
funziona come progettato. Da man gzip : viaggiare ricorsivamente nella struttura delle directory. Se uno dei nomi di file specificati sulla riga di comando è una directory , gzip scenderà nella directory e comprimerà tutti i file che trova lì (o li decomprimerà nel caso di gunzip). (enfasi mia)