Vous pouvez utiliser globstar.
Avec l' globstar
option shell activée, tout ce dont vous avez besoin est gzip -vk **/*.{css,html}
.
Le shell Bash a une globstar
option qui vous permet d'écrire des globs récursifs avec **
. shopt -s globstar
le permet. Mais vous ne voudrez peut-être pas le faire pour d'autres commandes que vous exécuterez plus tard, vous pouvez donc l'exécuter et votre gzip
commande dans un sous - shell à la place.
Cette commande gzip
s all .css
et .html
fichiers dans le répertoire courant l'un de ses sous-répertoires, l'un de leurs sous-répertoires, etc., en conservant les fichiers d'origine ( -k
) et en vous indiquant ce qu'il fait ( -v
):
(shopt -s globstar; gzip -vk **/*.{css,html})
Si vous souhaitez faire correspondre les noms de fichiers sans tenir compte de la casse afin que ces extensions avec certaines ou toutes les lettres en majuscule soient incluses, vous pouvez également activer l' nocaseglob
option shell:
(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})
;
sépare les deux commandes, et l'extérieur (
)
les fait exécuter dans un sous-shell. La définition d'une option shell dans un sous-shell ne la fait pas être définie dans le shell appelant. Si vous ne voulez activer globstar
vous pouvez exécuter shopt -s globstar
; alors vous pouvez simplement exécuter la commande:
gzip -vk **/*.{css,html}
Vous pouvez désactiver globstar
avec shopt -u globstar
. Vous pouvez vérifier s'il est actuellement activé avec shopt globstar
.
Comment ça fonctionne
La clé du fonctionnement de cette gzip
commande est que le shell effectue des extensions pour produire une liste de chaque fichier dans la hiérarchie de répertoires avec un nom correspondant, puis transmet chacun de ces noms de fichiers comme arguments à gzip
.
- L'expansion du corset se transforme
**/*.{css,html}
en **/*.css **/*.html
.
- Ensuite, le globbing étend ces deux modèles dans les noms de fichiers accessibles sous le répertoire actuel (
**
, en raison de globstar
) dont les noms de fichiers se composent de n'importe quoi ( *
) suivi du suffixe spécifié ( .css
ou .html
dans ce cas).
Cela ne correspond pas aux fichiers dont les noms commencent par.
ou ceux qui résident dans des répertoires nommés de cette façon. Vous n'avez probablement pas de tels fichiers HTML et CSS et, si vous en avez, vous ne voulez probablement pas les inclure. Mais si vous souhaitez les inclure, vous pouvez les faire correspondre explicitement en fonction de vos besoins. Par exemple, le changement **/*.{css,html}
de **/{,.}*.{css,html}
inclut les fichiers qui commencent par .
tout en ne recherche dans les dossiers qui le font.
Si vous souhaitez inclure à la fois les fichiers dont les noms commencent par .
et les fichiers dans les répertoires dont les noms commencent par .
, il existe une méthode plus simple et plus simple: activez l' dotglob
option shell.
(shopt -s globstar dotglob; gzip -vk **/*.{css,html})
Ou si vous voulez une correspondance insensible à la casse et une correspondance des noms de fichiers commençant par .
:
(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})
Il est possible, bien que très rare, **
de s'étendre à quelque chose de trop long.
Si vous avez un grand nombre de fichiers nommés de cette façon, cela peut échouer avec un message d'erreur expliquant que le shell ne peut pas construire la ligne de commande car ce serait trop long. (Même avec des milliers de fichiers, ce n'est généralement pas un problème.)
gzip
ne sera pas appelé du tout, donc vous n'obtiendrez pas un travail à moitié fait.
Si cette erreur se produit, ou si cela vous inquiète, vous pouvez utiliser find
avec -exec
, soit comme le décrit Steeldriver (avec {} \;
) ou comme je le décris ci-dessous (avec {} +
).
Vous pouvez utiliser find
avec l' -exec
action et +
pour l'efficacité.
La gzip
commande prend en charge les noms de plusieurs fichiers à compresser. Mais cette find
commande, bien qu'elle fonctionne bien et ne sera lente que si vous avez plusieurs fichiers, exécute la gzip
commande une fois pour chaque fichier:
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;
Cela fonctionne et vous pouvez certainement l'utiliser. ( .
recherche dans le répertoire courant. En plus de cela, c'est vraiment une façon légèrement différente d'écrire la commande dans la très bonne réponse de Steeldriver ; vous pouvez utiliser le style que vous préférez.)
Vous pouvez également faire find
passer plusieurs noms de fichiers gzip
et les exécuter autant de fois que nécessaire, ce qui est presque toujours une seule fois. Pour ce faire, utilisez +
au lieu de\;
. L' +
argument devrait venir juste après {}
. find
remplace +
par des noms de fichiers supplémentaires, le cas échéant.
find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
C'est très bien à utiliser +
même s'il n'y a que quelques fichiers correspondants, et quand il y en a beaucoup, cela peut être sensiblement plus rapide que d'avoir une gzip
invocation distincte pour chaque fichier.
Comme le mentionne Steeldriver , vous pouvez utiliser -iname
au lieu de -name
pour faire correspondre les fichiers dont le nom se termine comme .css
ou .html
mais avec des majuscules différentes. Cela correspond à l'activation nocaseglob
dans la globstar
méthode basée sur la description ci-dessus.
Enfin, vous n'avez probablement pas de fichiers ou de répertoires correspondants commençant par .
. Mais si vous le faites, find
les inclut automatiquement. Si vous souhaitez les exclure (comme cela se produit avec la globstar
méthode basée sur les détails ci-dessus lorsque dotglob
est désactivé), vous pouvez :
find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +
La globstar
méthode basée sur la description ci-dessus est plus simple à écrire, surtout si vous excluez les répertoires et les fichiers qui commencent par .
, car c'est la valeur par défaut.
Que ne pas faire ...
Les noms de fichiers peuvent contenir n'importe quel caractère à l'exception du séparateur de chemin /
et du caractère nul . Il existe de nombreuses techniques qui cassent des noms de fichiers étranges, et elles sont généralement plus compliquées que les techniques qui fonctionnent toujours. Je suggère donc de les éviter même si vous savez (ou pensez que vous savez) qu'ils vont bien dans votre situation spécifique. Et bien sûr, vous ne devez pas les utiliser si vous avez des noms de fichiers avec des caractères qui peuvent être traités spécialement, y compris des espaces.
Il est possible de diriger en toute sécurité la sortie de find
vers une autre commande qui la traite si vous utilisez -print0
ou une action similaire pour lui faire placer un caractère nul entre les chemins au lieu d'une nouvelle ligne , et pas autrement. Les noms de fichiers peuvent contenir des sauts de ligne (bien que je vous décourage de nommer délibérément des fichiers avec eux). Une find
commande avec l' -print
action - y compris les commandes de recherche sans action explicite, car -print
c'est la valeur par défaut - ne produit pas de sortie qui peut être canalisée en toute sécurité ou autrement fournie à une autre commande qui exécute une action sur les fichiers.
La sortie find
produite avec l' -print0
action peut être canalisée en toute sécurité xargs -0
(l' -0
indicateur indique xargs
d'attendre une entrée séparée par des valeurs nulles).
-r
fonctionne comme prévu. Depuis man gzip : parcourez la structure du répertoire de manière récursive. Si l'un des noms de fichiers spécifiés sur la ligne de commande sont des répertoires , gzip descendra dans le répertoire et compressera tous les fichiers qu'il y trouve (ou les décompressera dans le cas de gunzip). (c'est moi qui souligne)