ls ignore "pas de correspondance"

8

Je voudrais lister tous les fichiers dans un dossier appelé foldernamequi ont l'extension test, atestou btest.

Ma pensée immédiate était de courir ls ./foldername/*.{a,b,}test

Cela fonctionne bien à moins qu'il n'y ait rien avec l'extension atest, auquel cas j'obtiens l'erreur zsh: no matches found: ./foldername/*.atest.

Existe-t-il un moyen de simplement ignorer cette erreur et d'imprimer les fichiers qui existent?

J'ai besoin de cela pour travailler à la fois dans ZSH et BASH.

Jonathan Hodgson
la source
3
Rediriger l'erreur standard vers /dev/null?
DopeGhoti

Réponses:

9

Il peut être préférable de le faire avec find:

find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
John Moon
la source
1
peut-être avec un -maxdepth 1, pour imiter de plus près le lscomportement
Jeff Schaller
4
@JeffSchaller, notez qu'il -maxdepths'agit d'une extension GNU. Remarque 3 autres différences avec les globes: findincluraient des fichiers cachés, ne trieraient pas la liste et ne correspondraient pas aux noms de fichiers qui contiennent des octets ne formant pas des caractères valides (comme un $'St\xe9phane.atest'dans un environnement local UTF-8)
Stéphane Chazelas
11

Dans

ls -d ./foldername/*.{a,b,}test

{a,b,...} n'est pas un opérateur glob, c'est une expansion d'accolade, c'est d'abord étendu à:

ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test

Et chaque glob est développé individuellement, et si un glob ne correspond pas, la commande est annulée comme vous pouvez vous y attendre zsh(ou fish; in bash, vous avez besoin de l' failgloboption pour obtenir un comportement similaire).

Ici, vous souhaitez utiliser un seul glob qui correspond à tous ces fichiers et annuler la commande uniquement si ce glob ne correspond à aucun fichier:

ls -d ./foldername/*.(a|b|)test

Vous ne voulez pas utiliser nullglob, comme si aucun des globes ne correspondait, il s'exécuterait lssans arguments, alors listez le répertoire courant. cshnullglobest meilleur à cet égard car il supprime les globes non correspondants mais annule toujours la commande si tous les globs ne correspondent pas.

Vous ne voudriez pas l'utiliser nonomatch, car cela vous donnerait un comportement cassé bashqui serait dommage.

Pour une alternative glob qui fonctionne à la fois dans zshet bash, vous pouvez utiliser les globs ksh ( set -o kshglobin zshet shopt -s extglobin bash).

Ensuite, vous feriez:

ls -d ./foldername/*.@(a|b|)test

ou:

ls -d ./foldername/*.?([ab])test

Ajoutez l' failgloboption in bashpour éviter que le glob ne soit transmis littéralement lslorsqu'il ne correspond pas.

Voir Pourquoi nullglob n'est-il pas par défaut? pour plus d'informations.

Stéphane Chazelas
la source
Je ne sais pas pourquoi c'est une exigence de l'OP, mais y a-t-il un extglob qui fonctionne pour cela à la fois dans bash et zsh? J'ai dû utiliser ?(...)ou +(...)pour bash.
Jeff Schaller
@JeffSchaller, voir l'édition
Stéphane Chazelas