web-dev-qa-db-fra.com

Pourquoi LS -D listez-vous également des fichiers et où est-il documenté?

  • lorsque vous spécifiez ls --directory a* Il ne devrait pas indiquer que des annuaires commençant par a*
  • Mais il répertorie les fichiers et les répertoires commençant par a

questions:

  • où pourrais-je trouver une documentation à ce sujet, autre que man et info où je pense que j'ai bien regardé?
  • cela fonctionne-t-il seulement dans Bash?
49
erch

Les a* et *a* Syntaxe est implémentée par la coque, non par la commande ls.

Quand vous tapez

ls a*

à l'invite de votre shell, la coquille se développe a* Pour une liste de fichiers existants dans le répertoire actuel dont les noms commencent par a. Par exemple, cela pourrait augmenter a* à la séquence a1 a2 a3, et passez ceux comme des arguments à ls. La commande ls elle ne voit jamais le * personnage; Il ne voit que les trois arguments a1, a2, et a3.

Aux fins de l'expansion générique, les "fichiers" font référence à toutes les entités du répertoire actuel. Par exemple, a1 Peut-être être un fichier normal, a2 pourrait être un répertoire, et a3 pourrait être un lien symbolique. Ils ont tous des entrées d'annuaire et l'expansion générique de la coquille ne se soucie pas du type d'entité que ces entrées se rapportent.

Pratiquement tous les obus, vous êtes susceptible de rencontrer (Bash, SH, KSH, ZSH, CSH, TCSH, ...) Implémentez des caractères génériques. Les détails peuvent varier, mais la syntaxe de base de * correspondant à zéro ou plus de caractères et ? correspondant à un seul caractère est raisonnablement cohérent.

Pour bash en particulier, cela est documenté dans la section "Extransion de nom de fichier" du manuel Bash; Cours info bash et recherchez "Extransion de nom de fichier" ou voir ICI .

Le fait que cela soit fait par la coquille, et non par des commandes individuelles, a des conséquences intéressantes (et parfois surprenantes). La meilleure chose à ce sujet est que la manipulation générique est cohérente pour (très presque) Tous Commandes; Si la coquille n'a pas fait cela, certaines commandes ne se dérouleraient inévitablement pas, et d'autres le feraient de manière subtilement différente de la pensée de l'auteur "mieux". (Je pense que le shell de commandes Windows a ce problème, mais je ne suis pas assez familier avec cela pour commenter plus loin.)

D'autre part, il est difficile d'écrire une commande pour renommer plusieurs fichiers. Si vous écrivez:

mv *.log *.log.bak

cela échouera probablement, puisque*.log.bak est développé en fonction des fichiers existants dans le répertoire actuel. Il y a des commandes qui font ce genre de chose, mais ils doivent utiliser leur propre syntaxe pour spécifier la manière dont les fichiers doivent être renommés. Certaines commandes (telles que find) peuvent faire leur propre expansion générique; Vous devez citer les arguments pour supprimer l'expansion de Shell:

find . -name '*.txt' -print

L'expansion générique de la coquille est entièrement basée sur la syntaxe de l'argument de ligne de commande et l'ensemble des fichiers existants. IT ne peut pas être affecté par la signification de la commande. Par exemple, si vous voulez déplacer tout .log Fichiers jusqu'au répertoire parent, vous pouvez taper:

mv *.log ..

Si vous oubliez le ..:

mv *.log

et il arrive d'être exactement deux .log Fichiers dans le répertoire actuel, il se développera à:

mv one.log two.log

qui renommera one.log et clobber two.log.

[~ # ~] éditer [~ # ~] : et après 52 upvotes, une acceptation et un badge de gourou, peut-être que je devrais réellement répondre à la question dans le titre.

Les -d ou --directory Option à ls _ ne le dis pas de répertorier uniquement des répertoires. Il lui dit de répertorier les annuaires tout aussi eux-mêmes, pas leur contenu. Si vous donnez un nom de répertoire sous forme d'argument à ls, par défaut, il listera le Contenu du répertoire, car c'est généralement ce qui vous intéresse. Le -d L'option lui indique de répertorier simplement le répertoire lui-même. Cela peut être particulièrement utile lorsque combiné avec des caractères génériques. Si vous tapez:

ls -l a*

ls _ vous donnera une longue liste de chacun Fichier dont le nom commence par a et de contenu de chaque Répertoire dont le nom commence par a. Si vous souhaitez simplement une liste des fichiers et des répertoires, une ligne pour chacun, vous pouvez utiliser:

ls -ld a*

qui est équivalent à:

ls -l -d a*

Rappelez-vous à nouveau que la commande ls ne voit jamais le * personnage.

Quant à ce que cela soit documenté, man ls vous montrera la documentation de la commande ls sur n'importe quel système de type UNIX. Sur la plupart des systèmes à base de Linux, la commande ls fait partie du fichier GNU CARUTILS Package; si vous avez la commande info, soit info ls ou info coreutils ls devrait vous donner une documentation plus définitive et plus complète. D'autres systèmes, tels que MacOS, peuvent utiliser différentes versions de la commande ls et peuvent ne pas avoir la commande info; Pour ces systèmes, utilisez man ls. Et ls --help montrera A relativement Message d'utilisation court (117 lignes sur mon système) Si Utilisez le GNU Mise en œuvre du CARUTILS.

Et oui, même des experts doivent consulter la documentation de temps en temps. Voir aussi cette blague classique .

91
Keith Thompson

Voir la réponse de Keith Thompson; Mais expliquer pourquoi ls --directory a* Affiche les fichiers et répertoires: le --directory Option ne supprimait pas les fichiers non-Directoraux. Au lieu de cela, il répertorie les répertoires en tant que tels, alors qu'il indiquerait autrement leur contenu. Exemple:

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

Pour être très explicite, il est documenté dans la page LS (1) manuelle :

- D, -Directory Liste des entrées de répertoire à la place des matières et ne pas dréence Liens symboliques

pour être juste, les "entrées au lieu de contenus" pourrait probablement être plus explicite:

Si le fichier est un répertoire, affichez l'entrée de répertoire elle-même au lieu de répertorier le contenu de ce répertoire. Si le fichier est un lien symbolique, affichez l'entrée de liaison elle-même au lieu du fichier pointé par le lien.

6
msw

La documentation ne dit pas que les listes informatiques seulement entrées de répertoire sein plutôt lorsque ls reçoit le nom du répertoire qu'il répertorie la saisie de dir au lieu de C'est le 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 /
3
defhlt

La documentation fait partie du shell. En particulier, la coque effectue diverses expansions et substitutions dans un ordre particulier avant d'exécuter une commande.

La séquence de expansions de mots pour une coque compatible Bourne est

  1. Expansion de tilde
  2. Développement des paramètres
  3. Substitution de commande
  4. Expansion arithmétique
  5. Fractionnement de champ
  6. Expansion du chemin
  7. Démontage

Donc, la commande ls _ ne voit même pas le * caractères, les arguments sont déjà développés avec tous les fichiers correspondant au a* motif global. Ceci est contrairement à Windows, où chaque commande nécessitant un nom de fichier global doit mettre en œuvre cette fonctionnalité elle-même.

2
Jens

Le mot clé dont vous avez besoin (man bash) est "expansion du chemin de chemin".

1
Hauke Laging