pourquoi ls -d list aussi les files, et où est-il documenté?

  • lorsque vous spécifiez ls --directory a* il ne doit listr que les directorys commençant par a*
  • MAIS il répertorie les files ET directorys commençant par a

Questions :

  • où pourrais-je find de la documentation à ce sujet, autre que l' man et l' info où je pense que j'ai regardé à fond?
  • cela fonctionne-t-il uniquement dans BASH?

La syntaxe a a* et *a* est implémentée par le shell, et non par la command ls .

Lorsque vous tapez

 ls a* 

à l'invite de votre shell, le shell étend a* à une list de tous les files existants dans le directory courant dont les noms commencent par a . Par exemple, il peut étendre a* à la séquence a1 a2 a3 , et les transmettre comme arguments à ls . La command ls elle-même ne voit jamais le caractère * ; il ne voit que les trois arguments a1 , a2 et a3 .

Pour les besoins de l'expansion des caractères generics, "files" fait reference à toutes les entités du directory courant. Par exemple, a1 pourrait être un file normal, a2 pourrait être un directory et a3 pourrait être un lien symbolique. Ils ont tous des inputs de directory et l'extension de caractères generics du shell ne se soucie pas du type d'entité auquel ces inputs font reference.

Pratiquement tous les shells que vous traversez (bash, sh, ksh, zsh, csh, tcsh, …) implémentent des jokers. Les détails peuvent varier, mais la syntaxe de base de * correspondant à zéro ou plusieurs caractères et ? la correspondance d'un seul caractère est raisonnablement cohérente.

Pour bash en particulier, cela est documenté dans la section "Expansion du nom de file" du manuel bash; lancez info bash et searchz «Expansion de nom de file», ou voir ici .

Le fait que cela soit fait par le shell, et non par des commands individuelles, a des conséquences intéressantes (et parfois surprenantes). La meilleure chose à ce sujet est que la gestion des caractères generics est cohérente pour (presque) toutes les commands; si le shell ne le faisait pas, forcément certaines commands ne le dérangeraient pas et d'autres le feraient de manière subtilement différente que l'auteur pensait être "meilleure". (Je pense que le shell de command Windows a ce problème, mais je ne suis pas assez familier avec lui pour commenter plus loin.)

D'un autre côté, il est difficile d'écrire une command pour renommer plusieurs files. Si vous écrivez:

 mv *.log *.log.bak 

il échouera probablement, puisque *.log.bak est développé en fonction des files qui existent déjà dans le directory courant. Il y a des commands qui font ce genre de chose, mais elles doivent utiliser leur propre syntaxe pour spécifier comment les files doivent être renommés. Certaines commands (telles que find ) peuvent faire leur propre extension générique; vous devez citer les arguments pour supprimer l'expansion du shell:

 find . -name '*.txt' -print 

L'extension des caractères generics du shell est entièrement basée sur la syntaxe de l'argument de command line et de l'set des files existants. Il ne peut pas être affecté par la signification de la command. Par exemple, si vous souhaitez déplacer tous .log files .log vers le directory parent, vous pouvez taper:

 mv *.log .. 

Si vous oubliez le .. :

 mv *.log 

et il se trouve qu'il y a exactement deux files .log dans le directory courant, il va s'étendre à:

 mv one.log two.log 

qui renomme one.log et two.log .

EDIT : Et après 52 upvotes, un accepter, et un badge Gourou, peut-être que je devrais effectivement répondre à la question dans le titre.

L'option -d ou --directory à ls ne lui dit pas de listr seulement les directorys. Il lui dit de listr les directorys comme eux-mêmes, pas leur contenu. Si vous donnez un nom de directory en tant qu'argument à ls , il répertorie par défaut le contenu du directory, car c'est généralement ce qui vous intéresse. L'option -d indique qu'il répertorie uniquement le directory lui-même. Cela peut être particulièrement utile lorsqu'il est combiné avec des caractères generics. Si vous tapez:

 ls -la* 

ls vous donnera une longue list de chaque file dont le nom commence par a et du contenu de chaque directory dont le nom commence par a . Si vous voulez juste une list des files et directorys, une ligne pour chacun, vous pouvez utiliser:

 ls -ld a* 

ce qui équivaut à:

 ls -l -da* 

Rappelez-vous encore que la command ls ne voit jamais le caractère * .

Quant à savoir où cela est documenté, man ls vous montrera la documentation de la command ls sur à peu près n'importe quel système de type Unix. Sur la plupart des systèmes basés sur Linux, la command ls fait partie du package GNU coreutils; si vous avez la command info , info ls ou info coreutils ls devrait vous donner une documentation plus complète et plus complète. D'autres systèmes, tels que MacOS, peuvent utiliser différentes versions de la command ls et peuvent ne pas avoir la command 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 l'implémentation GNU coreutils.

Et oui, même les experts ont besoin de consulter la documentation de time en time. Voir aussi cette blague classique .

Voir la réponse de Keith Thompson; mais pour expliquer pourquoi ls --directory a* affiche les files et les directorys: L'option --directory ne supprime pas les files non-directory. Au lieu de cela, il répertorie les directorys en tant que tels, alors que sinon ils listraient leur contenu. Exemple:

 $ mkdir foo $ touch foo/bar $ ls foo bar $ ls --directory foo foo 

Pour être très explicite, il est documenté dans la page de manuel de ls (1) :

-d, – directory répertorie les inputs du directory au lieu du contenu, et ne déreference pas les liens symboliques

pour être juste, "les inputs au lieu du contenu" pourrait probablement être plus explicative:

Si FILE est un directory, affichez l'input du directory elle-même au lieu d'afficher le contenu de ce directory. Si FILE est un lien symbolique, affichez l'input de lien elle-même au lieu du file pointé par le lien.

Globant

Comme on l'a expliqué, l'expansion de * (et d'extensions similaires) s'appelle glob bing dans le jargon Unix, et est généralement une caractéristique du processeur de command (connu sous le nom de «shell» dans le jargon Unix). Donc, le globbing peut être utilisé dans beaucoup d'autres endroits aussi; tapez man 7 glob au shell d'une dissortingbution Linux classique (ou voyez ceci ) pour en savoir plus sur glob bing.

Au début d'Unix, glob était en fait implémenté par un programme séparé appelé /etc/glob (voir la page 10 de cet ancien manuel UNIX pour la documentation). De nos jours, c'est une routine de code fournie par les bibliothèques de codes, et est couramment utilisée par les shells. Source : Wikipedia .

Annuaires

Quant à savoir pourquoi ls -d répertorie les files ainsi que les directorys …

La page de manuel de ls explique pourquoi cela se produit, mais avec une explication très laconique. Voici donc une tentative d'explication élargie:

Par défaut, ls répertorie le contenu des directorys lorsqu'on leur donne leur nom, et fera la même chose pour les liens symboliques vers les directorys. L'option -d signifie "quand le ou les noms de directory (s)" (qui peuvent également être donnés implicitement par glob bing) , ne montrent que les _name_s du (des) directory (s), mais pas leur contenu. De même, lorsqu'il est fourni avec (explicitement ou implicitement ) un ou plusieurs noms de liens symboliques vers des directorys , affichez le nom de file du lien symbolique, pas le contenu du directory auquel il fait reference.

L'option -d n'a rien à faire, pour autant que je sache, avec quels éléments sont répertoriés; cela peut être fait (source: ici ) avec find , comme ceci: find . -maxdepth 1 -type d find . -maxdepth 1 -type d . Je ne suis pas sûr s'il y a un bon moyen de le faire seulement avec GNU ls . Voici quelques exemples d'utilisation de la command find .

Donc, en résumé: Par défaut, ls affiche le contenu des directorys lorsqu'on leur donne leur nom de path. -d modifie ce comportement, affichant uniquement le nom du directory lui-même, comme ce serait le cas pour un file standard.

La documentation ne dit pas qu'il ne répertorie que les inputs du directory bur plutôt quand ls reçoit le nom du directory, il répertorie l'input du directory au lieu de son contenu. La meilleure façon de comprendre est par exemple:

 > {ice} ~ :10:47 % ls -l / total 97 drwxr-xr-x 2 root root 4096 May 3 00:27 bin drwxr-xr-x 4 root root 1024 May 3 14:17 boot drwxr-xr-x 2 root root 4096 Apr 29 13:44 cdrom drwxr-xr-x 18 root root 4420 May 9 09:58 dev ... lrwxrwxrwx 1 root root 33 May 3 14:16 vmlinuz -> boot/vmlinuz-3.9.0-030900-generic lrwxrwxrwx 1 root root 29 May 3 11:07 vmlinuz.old -> boot/vmlinuz-3.8.0-19-generic > {ice} ~ :10:47 % ls -ld / drwxr-xr-x 25 root root 4096 May 3 14:16 / 

Le mot key dont vous avez besoin ( man bash ) est "Pathname Expansion".

La documentation fait partie du shell . En particulier, le shell exécute diverses expansions et substitutions dans un ordre particulier avant d'exécuter une command.

La séquence des expansions de mots pour un shell compatible Bourne est

  1. Tilde Expansion
  2. Expansion des parameters
  3. Substitution de command
  4. Expansion arithmétique
  5. Fractionnement de champ
  6. Expansion de nom de domaine
  7. Enlèvement de devis

Ainsi, la command ls ne voit même pas les * caractères, les arguments sont déjà développés avec tous les files correspondant au model a a* glob. Ceci est différent de Windows, où chaque command nécessitant un nom de file doit être implémentée elle-même.