Pourquoi «cat {foo}» ne produit-il pas foo, mais «cat {foo, bar}» le fait?

12

J'essayais de concaténer des fichiers texte dans des sous-dossiers et j'ai essayé:

cat ./{mainfolder1,mainfolder2,mainfolder3}/{subfolder1}/book.txt > out$var

Mais cela n'a rien retourné. Donc, j'ai essayé d'ajouter un «sous-dossier2» inexistant

cat ./{mainfolder1,mainfolder2,mainfolder3}/{subfolder1,subfolder2}/book.txt > out$var

Et cette fois, cela a fonctionné, concaténant les fichiers avec succès. Pourquoi cela se produit-il?

CDPF
la source
2
Utilisez echoau lieu de catpour voir quelle ligne de commande vous avez obtenue. (Ou utilisez set -xpour le débogage.)
Peter Cordes

Réponses:

22

Par définition, l'expansion d'accolade dans GNU Bash nécessite soit une expression de séquence soit une série de valeurs séparées par des virgules:

Les modèles à développer entre accolades prennent la forme d'un préambule facultatif, suivi soit d'une série de chaînes séparées par des virgules, soit d'une expression de séquence entre une paire d'accolades, suivie d'un post-scriptum facultatif.

Vous pouvez lire le manuel pour plus de détails.

Quelques exemples simples:

echo {subfolder1}
{subfolder1}

echo {subfolder1,subfolder2}
subfolder1 subfolder2

echo subfolder{1}
subfolder{1}

echo subfolder{1..2}
subfolder1 subfolder2
Arthur Hess
la source
21

{subfolder1}évalue à {subfolder1}, car il n'y a aucune alternative. Utilisez subfolder1plutôt.

Ignacio Vazquez-Abrams
la source
2
Notez qu'il est différent de in csh(d'où provient l'expansion de l'accolade), tcshou fish.
Stéphane Chazelas
1

Les accolades ne se développent que si elles ont des chaînes séparées par un coma, par exemple {abc, def} ou plage, par exemple {a..e} spécifiées entre elles.

Dans votre cas, vous pouvez simplement écrire subfolder1 sans le placer entre accolades car cela n'est pas nécessaire

cat ./{mainfolder1,mainfolder2,mainfolder3}/subfolder1/book.txt > out$var
Neo_Returns
la source
Malheureusement, /path/{a,}/filenames'étend aux deux chaînes /path/a/filenameet /path//filename, ce qui peut être indésirable.
Kusalananda
merci à @Kusalananda de m'avoir corrigé, oui bash fournira un avertissement lors d'une "redirection ambiguë"
Neo_Returns
Non, vous obtenez ambiguous redirect si vous essayez de rediriger vers un fichier donné par une variable sans guillemets qui n'a pas de valeur, par exemple echo 'hello' >$idontexist.
Kusalananda
1
... ou si le nom de fichier dans la redirection est étendu à plusieurs mots. Comme > *.txtavec plusieurs .txtfichiers, ou > $files'il $filecontient des espaces. Mais bien sûr, il n'y a rien d'ambigu dans le fait de donner catplusieurs arguments
ilkkachu