Avec bash, définissez les paramètres glob afin que les correspondances manquantes ne déclenchent pas d'erreur :
shopt -u failglob # avoid failure report (and discarding the whole line).
shopt -s nullglob # remove (erase) non-matching globs.
ls ?c c?
Le point d'interrogation est un caractère global représentant un seul caractère. Puisque vous voulez des noms de fichiers à deux caractères, l'un d'eux doit être un c , et donc c'est soit le premier caractère, soit le dernier caractère.
Avec shopt -s dotglob cela afficherait également un fichier nommé .c .
S'il n'y a pas de fichiers correspondants, la définition de ces options du shell entraîne la suppression de tous les arguments, ce qui se traduit par un simple ls -- listant n'importe quoi/tout par défaut.
Utilisez ceci à la place :
shopt -s nullglob ## drop any missing globs
set -- ?c c? ## populate the [email protected] array with (any) matches
if [ $# -gt 0 ] ## if there are some, list them
ls -d "[email protected]"
fi
Je pense que la meilleure façon est d'utiliser find :
find . -type f -name '*c*' -name '??'
Cela effectuera une recherche récursive. Pour lister uniquement les fichiers du répertoire courant :
find . ! -name . -prune -type f -name '*c*' -name '??'
Si les fichiers existent (et n'ont pas de caractères d'échappement comme \c ), vous pouvez utiliser un glob :
echo ?c c?
qui correspondra aux fichiers qui ont un caractère (? ) suivi d'un c ou qui ont un c suivi d'un caractère (? ).
Mais échouera avec les noms de fichiers qui commencent par un tiret comme -n ou -e ou avec des barres obliques inverses comme \c ou \n avec echo comme -e et -n sont spéciaux pour (certains shells) echo et \c ou \n serait interprété comme une séquence d'échappement (\c termine la sortie et \n imprime une nouvelle ligne, pas les caractères textuels \n dans certaines implémentations shell de echo et avec bash lorsque l'option shopt -s xpg_echo est réglé). D'autres applications ou utilitaires (comme ls ) aura d'autres options et peut échouer avec de nombreux autres caractères commençant par un tiret ou interpréter d'autres caractères d'échappement dans les noms de fichiers.
Listera également un fichier nommé cc deux fois.
-
Si un fichier peut commencer par un tiret (comme -n), utilisez :
$ ls -d -- ?n -nOu mieux :
$ ls -d ./?n ./-n
Mises en garde
-
Glob ne correspond à aucun fichier.
-
Si les fichiers n'existent pas, le glob ne sera pas développé et le glob sera imprimé dans sa forme d'origine.
$ echo ?m m? ?m m? -
Sauf en zsh.
$ zsh -c 'echo ?m m?' zsh:1: no matches found: ./m?Le shell se terminera avec une erreur.
Ce comportement est contrôlé par lenomatchde Zsh option.$ zsh -c 'setopt +o nomatch; echo ?m m?' ?m m?Ou :
$ zsh -c 'echo ?m(N) m?(N)' ?m m?Mais cela imprimera
mmdeux fois. -
Dans bash, vous pourriez obtenir un résultat similaire à zsh si l'option shell
failglobest défini :$ bash -c 'shopt -s failglob; echo ?m m?' bash: no match: ?mMais le script ne s'arrêtera pas, le shell ne se fermera pas. Eh bien, techniquement, la ligne où le glob est utilisé n'est pas exécutée davantage mais l'exécution reprend à la ligne de script suivante.
-
En bash, vous pouvez définir l'option
nullglobpour supprimer les globs qui ne correspondent pas :$ bash -c 'shopt -s nullglob; echo ?m m? done' done
-
-
Utilisation de ls (similaire à d'autres programmes)
-
Avec les fichiers correspondants, il n'y aura pas de problème, mais les répertoires seront également mis en correspondance (et répertoriés) :
$ ls ?c c? bc cz sc ac: hjkMieux vaut utiliser
-davecls(les répertoires seront inclus mais pas développés).$ ls -d ?c c? ac bc cz sc -
Les globs ne correspondent pas à un fichier (ou un répertoire)
Alors
lssignalera un échec$ ls ?m m? ls: cannot access '?m': No such file or directoryD'autres programmes pourraient (probablement) ne pas faire des vérifications similaires.
-
Utilisation de
nullglobavec bash donnera une liste vide à ls, donc, il listera le contenu ou le pwd comme si seulementlsa été exécuté :$ ls ?m m? ac a.out cz 3 b sc ab bcCela pourrait être évité en utilisant
./$ ls -d ./?m ./m? ls: cannot access './?m': No such file or directory ls: cannot access './m?': No such file or directory
-
Ou vous pouvez utiliser une regex de recherche (mais elle traversera les sous-répertoires avec prune manquant) (Notez que cela ne répétera pas un fichier appelé cc) :
$ find . ! -name . -prune -regex '.*/\(.c\|c.\)'
./ac
./cc
./sc
./bc
./cz