Puedes usar globstar.
Con la globstar
opción de shell habilitada, todo lo que necesita es gzip -vk **/*.{css,html}
.
El shell Bash tiene una globstar
opción que te permite escribir globos recursivos con **
. shopt -s globstar
lo habilita Pero es posible que no desee hacer eso para otros comandos que ejecute más tarde, por lo que puede ejecutarlo junto con su gzip
comando en una subshell .
Este comando gzip
es todo .css
y .html
los archivos en el directorio actual de cualquiera de sus subdirectorios, cualquiera de sus subdirectorios, etc., manteniendo los archivos originales ( -k
) y que lo que está haciendo (diciendo -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Si desea hacer coincidir los nombres de archivo sin distinción entre mayúsculas y minúsculas para que se incluyan esas extensiones con algunas o todas las letras en mayúscula, también puede habilitar la nocaseglob
opción de shell:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
separa los dos comandos, y el exterior (
)
hace que se ejecuten en una subshell. Establecer una opción de shell en un subshell no hace que se establezca en el shell de llamada. Si no desea habilitar globstar
continuación, puede ejecutar shopt -s globstar
; entonces puedes ejecutar el comando:
gzip -vk **/*.{css,html}
Puede deshabilitar globstar
con shopt -u globstar
. Puede verificar si está habilitado actualmente con shopt globstar
.
Cómo funciona
La clave de cómo funciona este gzip
comando es que el shell realiza expansiones en él para producir una lista de cada archivo en la jerarquía del directorio con un nombre coincidente, luego pasa cada uno de estos nombres de archivo como argumentos gzip
.
- La expansión de llaves se convierte
**/*.{css,html}
en **/*.css **/*.html
.
- Luego, globbing expande esos dos patrones en los nombres de archivos accesibles bajo el directorio actual (
**
debido a globstar
) cuyos nombres de archivo consisten en cualquier cosa ( *
) seguido del sufijo especificado ( .css
o .html
en este caso).
Esto no coincide con los archivos cuyos nombres comienzan con.
los que residen en directorios nombrados de esta manera. Probablemente no tenga dichos archivos HTML y CSS y, si los tiene, probablemente no quiera incluirlos. Pero si desea incluirlos, puede hacerlos coincidir explícitamente según sus necesidades. Por ejemplo, cambiar **/*.{css,html}
a **/{,.}*.{css,html}
incluye archivos que comienzan .
mientras aún no buscan en carpetas que sí lo hacen.
Si desea que se incluyan tanto los archivos cuyos nombres comiencen .
como los archivos en directorios cuyos nombres comiencen con .
, hay una forma más limpia y sencilla: habilitar la dotglob
opción de shell.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
O si desea la coincidencia entre mayúsculas y minúsculas y la coincidencia de nombres de archivo que comienzan con .
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Es posible, aunque muy raro, **
expandirse a algo demasiado tiempo.
Si tiene una gran cantidad de archivos nombrados de esta manera, esto puede fallar con un mensaje de error que explica que el shell no puede construir la línea de comando porque sería demasiado largo. (Incluso con miles de archivos, esto generalmente no es un problema).
gzip
no será llamado en absoluto, por lo que no obtendrá un trabajo a medio hacer.
Si ocurre este error, o si le preocupa, puede usarlo find
con -exec
, como lo describe steeldriver (con {} \;
) o como lo describo a continuación (con {} +
).
Se puede usar find
con la -exec
acción y +
para la eficiencia.
El gzip
comando admite recibir nombres de varios archivos para comprimir. Pero este find
comando, aunque funciona bien y no será lento a menos que tenga muchos archivos, ejecuta el gzip
comando una vez para cada archivo:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Esto funciona, y definitivamente puedes usarlo. ( .
busca desde el directorio actual. Además de eso, es realmente una forma ligeramente diferente de escribir el comando en la muy buena respuesta de steeldriver ; puede usar el estilo que prefiera).
También puede find
pasar varios nombres de archivo gzip
y ejecutarlo solo las veces que sea necesario, que casi siempre es solo una vez. Para hacer eso, use en +
lugar de\;
. El +
argumento debería venir justo después {}
. find
reemplaza +
con nombres de archivo adicionales, si los hay.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
Está bien usarlo +
incluso si solo hay unos pocos archivos coincidentes, y cuando hay muchos de ellos, puede ser notablemente más rápido que tener una gzip
invocación separada para cada archivo.
Como menciona Steeldriver , puede usar en -iname
lugar de -name
hacer coincidir archivos cuyo nombre termine como .css
o .html
pero con diferentes mayúsculas. Esto corresponde a habilitar nocaseglob
en el globstar
método basado en lo descrito anteriormente.
Finalmente, probablemente no tenga ningún archivo o directorio coincidente que comience con .
. Pero si lo hace, find
los incluye automáticamente. Si desea excluirlos (como sucede con el globstar
método basado en detalles detallado anteriormente cuando dotglob
está desactivado), puede :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
La globstar
forma basada en lo descrito anteriormente es más simple de escribir, especialmente si excluye directorios y archivos que comienzan .
, ya que ese es el valor predeterminado.
Que no hacer ...
Los nombres de archivo pueden contener cualquier carácter, excepto el separador de ruta /
y el carácter nulo . Existen muchas técnicas que se rompen en nombres de archivo extraños, y generalmente son más complicadas que las técnicas que siempre funcionan. Por lo tanto, sugiero evitarlos incluso cuando sepa (o piense que sabe) que están bien en su situación específica. Y, por supuesto, no debe usarlos si puede tener nombres de archivo con caracteres que pueden tratarse especialmente, incluidos los espacios.
Es posible canalizar de forma segura la salida de find
otro comando que lo procesa si usa -print0
o una acción similar para hacer que coloque un carácter nulo entre las rutas en lugar de una nueva línea , y no de otra manera. Los nombres de archivo pueden contener nuevas líneas (aunque te desaliento de nombrar deliberadamente archivos con ellos). Un find
comando con la -print
acción, incluidos los comandos de búsqueda sin acción explícita, ya que -print
es el valor predeterminado, no produce resultados que se puedan canalizar de forma segura o de otro modo a otro comando que realice una acción en los archivos.
La salida que se find
produce con la -print0
acción se puede canalizar de forma segura xargs -0
(el -0
indicador indica que xargs
debe esperar una entrada separada por nulos).
-r
Funciona según lo diseñado. Desde man gzip : recorre la estructura de directorios de forma recursiva. Si alguno de los nombres de archivo especificados en la línea de comando son directorios , gzip descenderá al directorio y comprimirá todos los archivos que encuentre allí (o los descomprimirá en el caso de gunzip). (énfasis mío)