La syntaxe a*
et *a*
est implémentée par le shell, pas par la ls
commande.
Quand vous tapez
ls a*
à l'invite de votre shell, celui-ci se développe a*
en une liste de tous les fichiers existants dans le répertoire en cours dont le nom commence par a
. Par exemple, il peut être étendu a*
à la séquence a1 a2 a3
et transmis comme arguments à ls
. La ls
commande elle-même ne voit jamais le *
personnage; il ne voit que les trois arguments a1
, a2
et a3
.
Aux fins d'expansion des caractères génériques, "fichiers" fait référence à toutes les entités du répertoire actuel. Par exemple, il a1
peut s'agir d'un fichier normal, d' a2
un répertoire et d' a3
un lien symbolique. Ils ont tous des entrées de répertoire, et l'extension générique du shell ne tient pas compte du type d'entité auquel ces entrées font référence.
Pratiquement tous les shells rencontrés (bash, sh, ksh, zsh, csh, tcsh, ...) implémentent des caractères génériques. Les détails peuvent varier, mais la syntaxe de base consistant à faire *
correspondre zéro ou plusieurs caractères et à faire ?
correspondre n'importe quel caractère est raisonnablement cohérente.
Pour bash en particulier, cela est documenté dans la section "Développement du nom de fichier" du manuel bash; lancez info bash
et cherchez "extension de nom de fichier", ou voyez ici .
Le fait que cela soit fait par le shell, et non par des commandes individuelles, a des conséquences intéressantes (et parfois surprenantes). La meilleure chose à ce sujet est que la gestion des caractères génériques est cohérente pour (presque) toutes les commandes; Si le shell ne le faisait pas, certaines commandes ne le dérangeraient inévitablement pas, et d'autres le feraient de manières légèrement différentes que l'auteur pensait "meilleures". (Je pense que le shell de commande Windows a ce problème, mais je ne le connais pas suffisamment pour commenter davantage.)
D'autre part, il est difficile d'écrire une commande pour renommer plusieurs fichiers. Si vous écrivez:
mv *.log *.log.bak
il échouera probablement car il *.log.bak
est développé en fonction des fichiers déjà présents dans le répertoire en cours. Certaines commandes font ce genre de choses, mais elles doivent utiliser leur propre syntaxe pour spécifier comment les fichiers doivent être renommés. Certaines commandes (telles que find
) peuvent créer leur propre développement générique. vous devez citer les arguments pour supprimer l'expansion du shell:
find . -name '*.txt' -print
Le développement des caractères génériques du shell repose entièrement sur la syntaxe de l'argument de ligne de commande et de l'ensemble des fichiers existants. Il ne peut pas être affecté par le sens de la commande. Par exemple, si vous souhaitez déplacer tous les .log
fichiers vers le répertoire parent, vous pouvez taper:
mv *.log ..
Si vous oubliez le ..
:
mv *.log
et il se trouve qu'il y a exactement deux .log
fichiers dans le répertoire courant, il va s'étendre à:
mv one.log two.log
qui va renommer one.log
et clobber two.log
.
EDIT : Et après 52 votes positifs, un accept et un badge Guru, je devrais peut-être répondre à la question dans le titre.
L' option -d
ou ne dit pas de ne lister que les répertoires. Il lui dit de lister les répertoires comme eux-mêmes, pas leur contenu. Si vous donnez un nom de répertoire comme argument , par défaut, le contenu du répertoire sera répertorié , car c'est généralement ce qui vous intéresse. L' option lui dit de ne répertorier que le répertoire lui-même. Cela peut être particulièrement utile lorsqu'il est combiné avec des caractères génériques. Si vous tapez:--directory
ls
ls
-d
ls -l a*
ls
vous donnera une longue liste de chaque fichier dont le nom commence par a
, et du contenu de chaque répertoire dont le nom commence par a
. Si vous voulez juste une liste des fichiers et des répertoires, une ligne pour chacun, vous pouvez utiliser:
ls -ld a*
qui équivaut à:
ls -l -d a*
Rappelez-vous à nouveau que la ls
commande ne voit jamais le *
personnage.
Quant à savoir où cela est documenté, man ls
vous montrera la documentation de la ls
commande sur n'importe quel système de type Unix. Sur la plupart des systèmes basés sur Linux, la ls
commande fait partie du paquet GNU coreutils; si vous avez la info
commande, vous devriez info ls
ou info coreutils ls
vous fournir une documentation plus complète et plus définitive. D'autres systèmes, tels que MacOS, peuvent utiliser différentes versions de la ls
commande et ne pas en disposer info
; pour ces systèmes, utilisez man ls
. Et ls --help
affichera un message d'utilisation relativement court (117 lignes sur mon système) si vous utilisez la mise en œuvre GNU coreutils.
Et oui, même les experts doivent consulter la documentation de temps en temps. Voir aussi cette blague classique .