La syntaxe a*et *a*est implémentée par le shell, pas par la lscommande.
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 a3et transmis comme arguments à ls. La lscommande elle-même ne voit jamais le *personnage; il ne voit que les trois arguments a1, a2et 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 a1peut s'agir d'un fichier normal, d' a2un répertoire et d' a3un 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 bashet 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.bakest 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 .logfichiers 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 .logfichiers dans le répertoire courant, il va s'étendre à:
mv one.log two.log
qui va renommer one.loget 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 -dou 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:--directorylsls-d
ls -l a*
lsvous 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 lscommande ne voit jamais le *personnage.
Quant à savoir où cela est documenté, man lsvous montrera la documentation de la lscommande sur n'importe quel système de type Unix. Sur la plupart des systèmes basés sur Linux, la lscommande fait partie du paquet GNU coreutils; si vous avez la infocommande, vous devriez info lsou info coreutils lsvous fournir une documentation plus complète et plus définitive. D'autres systèmes, tels que MacOS, peuvent utiliser différentes versions de la lscommande et ne pas en disposer info; pour ces systèmes, utilisez man ls. Et ls --helpaffichera 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 .