J'essaie de compresser tous les fichiers sur Ubuntu qui ont l'extension de fichier .css, .html ou .js. dans un répertoire supérieur et tous les sous-répertoires. Je souhaite conserver les fichiers d'origine et écraser le fichier .gz, s'il existe déjà.
Donc, quand j'ai n fichiers, je veux conserver ces n fichiers et créer n fichiers d'archives supplémentaires. Pas seulement un.
J'ai essayé d'exécuter un script qui ressemble à ceci:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Premièrement: je dois avoir une ligne dans ce script pour chaque extension de fichier que je veux compresser. C'est bon, mais j'espère trouver une meilleure façon
Deuxième et plus important: cela ne fonctionne pas. Bien que -r doive faire le travail, les sous-répertoires sont inchangés. Le fichier gzip n'est créé que dans le répertoire supérieur.
Qu'est-ce que j'oublie ici?
Btw: Ce qui suit est un bug dans la sortie verbeuse, non? Lors de l'utilisation des options -k et -v
-k, --keep keep (don't delete) input files
-v, --verbose verbose mode
La sortie détaillée indique qu'il remplace le fichier, bien que «remplacer» signifie que le fichier d'origine n'existe pas après le remplacement. Quoi qu'il en soit, ce n'est que la sortie.
$ ls
index.html subdir1 testfile testfile.css.gz
javaclass.java subdir2 testfile.css
$ gzip -fkv *.css
testfile.css: 6.6% -- replaced with testfile.css.gz
$ ls
index.html subdir1 testfile testfile.css.gz
javaclass.java subdir2 testfile.css
-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)Réponses:
vous pouvez le faire avec une boucle for pour trouver chaque fichier puis le compresser:
la source
-r
option ne fonctionne pas-k
et-f
fonctionne, je peux donc les utiliser comme ceci: pour i dansfind | grep -E "\.css$|\.html$"
; do gzip -vkf "$ i"; fait``...`
fournit une chaîne, pas une liste.for
utilise le séparateur de champ interne ($IFS
) pour décider où cette chaîne doit être fractionnée. Par défaut, il se divise en sauts de ligne, tabulations et espaces, donc si vous avez un fichier appelénew style.css
, les commandesgzip new
etgzip style.css
seront exécutées.export IFS=$'\n'
juste avant lafor
boucle.j'utiliserais
Remplacez-le
name
pariname
si vous souhaitez faire correspondre les extensions à la casse (c'est-à-dire inclure.CSS
et / ou.HTML
extensions). Vous pouvez omettre le/path/to/dir
si vous souhaitez démarrer la recherche récursive à partir du répertoire actuel.la source
--keep
commutateur, oui, il entraîne la conservation des fichiers d'origine. Omettez-le si vous souhaitez qu'ils soient supprimés une fois compressés.Pour obtenir la liste des fichiers:
Et pour compresser tous ces fichiers:
la source
tar
la liste des fichiers en sortiefind
, plutôt que les fichiers eux-mêmes?-T
optiontar
traite l'entrée en tant que noms de fichiers.J'ai utilisé la réponse de Steeldriver , mais j'aime la compléter avec les options
--best
et--force
.cd
dans n'importe quel dossier et tapez ce code. Tous vos fichiers correspondants seront compressés.--best
pour le meilleur taux de compression.--force
pour remplacer sans demander s'il existe déjà un fichier compressé.la source
Vous pouvez utiliser globstar.
Avec l'
globstar
option shell activée, tout ce dont vous avez besoin estgzip -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 votregzip
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
):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:;
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 activerglobstar
vous pouvez exécutershopt -s globstar
; alors vous pouvez simplement exécuter la commande:Vous pouvez désactiver
globstar
avecshopt -u globstar
. Vous pouvez vérifier s'il est actuellement activé avecshopt 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
.**/*.{css,html}
en**/*.css **/*.html
.**
, en raison deglobstar
) 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.Ou si vous voulez une correspondance insensible à la casse et une correspondance des noms de fichiers commençant par
.
: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 cettefind
commande, bien qu'elle fonctionne bien et ne sera lente que si vous avez plusieurs fichiers, exécute lagzip
commande une fois pour chaque fichier: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 fichiersgzip
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.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 unegzip
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'activationnocaseglob
dans laglobstar
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 laglobstar
méthode basée sur les détails ci-dessus lorsquedotglob
est désactivé), vous pouvez :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). Unefind
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 indiquexargs
d'attendre une entrée séparée par des valeurs nulles).la source
Pour compresser récursivement tous les fichiers d'un dossier / sous-dossier:
Dézipper:
la source
`
`
syntaxe, mais le problème s'applique également lors de l'utilisation de la$(
)
syntaxe.)