5 votes

shopt : qu'est-ce qui ne va pas avec "&&" ?

Je ne comprends pas pourquoi, lorsque je les fais séparément, cela fonctionne, mais avec && il ne le fait pas (ce n'est pas un ( problème comme ici )... que me manque-t-il ?

11:20:06 $ shopt -s extglob && shopt -s globstar && for f in **/*.@(jpg|jpeg|png|gif); do [[ -f "$f.webp" ]] || cwebp -quiet -q 80 "$f" -o "$f.webp"; done
bash: syntax error near unexpected token `('
11:20:11 $ shopt -s extglob && shopt -s globstar 
11:20:16 $ for f in **/*.@(jpg|jpeg|png|gif); do [[ -f "$f.webp" ]] || cwebp -quiet -q 80 "$f" -o "$f.webp"; doneError! Could not process file img/colorpicker/colormap.gif
11:20:23 $

11voto

rwc9u Points 532

Comme la première version tient sur une seule ligne, le Shell doit analyser l'ensemble avant de l'exécuter. Mais **/*.@(jpg|jpeg|png|gif) n'est valable que pour la syntaxe après shopt -s extglob a été exécuté ... c'est-à-dire une fois que la ligne est passée par la phase d'analyse.

Si cela doit être une réplique, je ne connais pas de bonne façon de le faire. Mais vous devriez pouvoir tricher en utilisant une expansion d'accolade au lieu d'un glob étendu, et en modifiant le test pour les fichiers :

shopt -s globstar && for f in **/*.{jpg,jpeg,png,gif}; do [[ -f "$f" && ! -f "$f.webp" ]] && cwebp -quiet -q 80 "$f" -o "$f.webp"; done

Il convient de noter que, dans la mesure où globstar prend effet lorsque le caractère générique est développé, et non lors de la première passe d'analyse, ce problème ne s'applique pas à lui.

Explication : bash développe les accolades avant d'étendre les caractères génériques, donc

for f in **/*.{jpg,jpeg,png,gif};

s'étend à

for f in **/*.jpg **/*.jpeg **/*.png **/*.gif;

...puis chacun de ces motifs est développé séparément. Il y a un problème potentiel : s'il n'y a pas au moins un fichier correspondant à chacun des quatre motifs, le(s) motif(s) non correspondant(s) sera(ont) laissé(s) tel(s) qu'il(s) est(sont) un(s) espace(s) vide(s).

Par exemple, s'il n'y a que des fichiers .jpg et .png, la liste entièrement développée pourrait contenir quelque chose comme ceci :

path/to/image1.jpg
path/to/image2.jpg
**/*.jpeg
path/to/image3.png
**/*.gif

...et il continuera à exécuter la boucle avec chacun d'entre eux, y compris **/*.jpeg y **/*.gif . C'est pourquoi j'ai dû modifier le test à l'intérieur de la boucle en

[[ -f "$f" && ! -f "$f.webp" ]] && cwebp ...

En -f "$f" échouera sur les caractères génériques non développés et l'empêchera d'essayer de créer des versions webp de fichiers inexistants. Vous pouvez également utiliser ceci, qui est plus proche du test original :

[[ ! -f "$f" || -f "$f.webp" ]] || cwebp ...

Mais je pensais que c'était plus intuitif sous l'autre forme.

BTW, une autre solution possible pour résoudre le problème des caractères génériques non appariés est d'ajouter shopt -s nullglob ce qui a pour effet de faire disparaître les éléments non appariés.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X