Réponses:
ls
liste les fichiers et le contenu des répertoires, il est transmis en tant qu'arguments, et si aucun argument n'est fourni, il répertorie le répertoire en cours. On peut également lui transmettre un certain nombre d’options qui affectent son comportement (voir man ls
pour plus de détails).
Si ls
un argument appelé est passé *
, il cherchera un fichier ou un répertoire appelé *
dans le répertoire actuel et le listera comme n'importe quel autre. ls
ne traite pas le *
personnage autrement que par un autre.
Cependant, s'il ls *
s'agit d'une ligne de commande shell , le shell l'étendra *
conformément aux règles de globbing du shell correspondant (également appelées génération de noms de fichiers ou extension de noms de fichiers ).
Alors que différents shells prennent en charge différents opérateurs globbing, la plupart d’entre eux s’accordent sur le plus simple *
. *
en tant que modèle, cela signifie un nombre quelconque de caractères, de sorte *
qu'un élément glob
sera étendu à la liste des fichiers des répertoires actuels qui correspondent à ce modèle. Il existe toutefois une exception, à savoir qu'un caractère point ( .
) dans un nom de fichier doit être explicitement mis en correspondance. Il est donc *
étendu à la liste des fichiers et des répertoires ne commençant pas par .
(dans l'ordre lexicographique).
Par exemple, si le répertoire courant contient les fichiers appelés .
, ..
, .foo
, -l
et foo bar
, *
sera étendu par l'enveloppe à deux arguments pour passer à ls
: -l
et foo bar
, donc ce sera comme si vous aviez tapé:
ls -l "foo bar"
ou
'ls' "-l" foo\ bar
Quelles sont les trois manières d'exécuter exactement la même commande? Dans les 3 cas, les 3 arguments: "ls", "-l" et "foo bar" seront transmis à la ls
commande (qui sera probablement exécutée à partir /bin/ls
d'une recherche dans les répertoires mentionnés dans $PATH
).
Incidemment, dans ce cas, ls
le premier (à proprement parler le second ) sera traité comme une option.
Maintenant, comme je l'ai dit, différents obus ont différents opérateurs globbing. Il y a quelques décennies, a été zsh
introduit l' **/
opérateur¹ qui correspond à n'importe quel niveau de sous-répertoires, abréviation de (*/)#
et ***/
qui est identique, sauf qu'il suit des liens symboliques lors de la descente des répertoires.
Il y a quelques années (juillet 2003 ksh93o+
), a ksh93
décidé de copier ce comportement mais a décidé de le rendre facultatif et ne couvrait que le **
cas (non ***
). De plus, alors que **
seul n’était pas spécial zsh
(signifie exactement la même chose que *
dans d’autres shells traditionnels, car **
signifie un nombre quelconque de caractères suivi d’un nombre quelconque de caractères), en ksh93, **
signifie la même chose que **/*
(ainsi, tout fichier ou répertoire situé en dessous du nom actuel). (excluant les fichiers cachés).
bash
copié ksh93
quelques années plus tard (Février 2009, bash 4.0), avec la même syntaxe , mais une différence malheureuse: années bash **
était comme zsh
l » ***
, qui est elle suivait les liens symboliques lors récursion dans les sous-répertoires qui ne sont généralement pas ce que vous voulez faire et peut avoir des effets secondaires désagréables. Il a été partiellement corrigé dans bash-4.3 en ce que les liens symboliques étaient toujours suivis, mais la récursivité s’arrêtait là. Il a été entièrement corrigé dans la version 5.0.
yash
ajouté **
dans la version 2.0 en 2008, activé avec l' extended-glob
option. Sa mise en œuvre est plus proche de zsh
celle dans laquelle **
seule n'est pas spéciale. Dans la version 2.15 (2009), il ajoutait ***
like in zsh
et deux de ses propres extensions: .**
et .***
pour inclure les répertoires cachés lors du récursif (dans zsh
, le D
qualificatif glob (comme dans **/*(D)
) considérera les fichiers et répertoires cachés, mais si vous ne voulez que parcourir mais ne développez pas les fichiers cachés, vous devez ((*|.*)/)#*
ou **/[^.]*(D)
).
La coquille de poisson prend également en charge **
. Comme la version précédente de bash
, il suit les liens symboliques lors de la descente de l’arborescence. Dans cette coquille cependant ce **/*
n'est pas la même chose que **
. **
est plutôt une extension *
qui peut s’étendre sur plusieurs répertoires. En fish
, **/*.c
correspondra a/b/c.c
mais non a.c
, tout en a**.c
correspondront a.c
et ab/c/d.c
et zsh
est , **/.*
par exemple , doit être écrit .* **/.*
. Là, ***
est compris comme **
suivi par *
donc le même que **
.
tcsh
a également ajouté une globstar
option dans la version 6.11.01 (mai 2010) et prend en charge les deux méthodes **
et ***
à la fois zsh
.
Donc, dans tcsh
, bash
et ksh93
, (lorsque l’option correspondante est activée ( globstar
)) ou fish
, **
développe tous les fichiers et répertoires situés sous le répertoire actuel, et ***
est identique à **
pour fish
, un lien symbolique traversant **
pour tcsh
avec globstar
, et identique à *
dans bash
et ksh93
(bien que Il n’est pas impossible que les futures versions de ces shells traversent également des liens symboliques).
Ci-dessus, vous avez remarqué la nécessité de vous assurer qu'aucune des extensions ne soit interprétée comme une option. Pour cela, vous feriez:
ls -- *
Ou:
ls ./*
Il existe certaines commandes (peu importe ls
) dans lesquelles la seconde est préférable, car même avec --
certains noms de fichiers, ceux-ci peuvent être traités de manière spécifique. Il est le cas de -
la plupart des services publics de texte, cd
et , pushd
et les noms de fichiers contenant le =
caractère pour awk
par exemple. La présélection ./
de tous les arguments supprime leur signification particulière (au moins pour les cas mentionnés ci-dessus).
Il convient également de noter que la plupart des shells ont un certain nombre d’options qui affectent le comportement de globalisation (par exemple, si les fichiers de points sont ignorés ou non, l’ordre de tri, ce qu’il faut faire s’il n’ya pas de correspondance ...), voir aussi le $FIGNORE
paramètre dansksh
En outre, dans chaque coquille , mais csh
, tcsh
, fish
et zsh
, si le modèle englobement ne correspond à aucun fichier, le modèle est passé comme un argument non dilatée qui provoque la confusion et peut - être des bugs. Par exemple, s'il n'y a pas de fichier non caché dans le répertoire en cours
ls *
Appellera en fait ls
avec les deux arguments ls
et *
. Et comme il n'y a pas de fichier du tout, donc pas appelé *
non plus, vous verrez un message d'erreur de la part de ls (pas le shell) comme suit:, ls: cannot access *: No such file or directory
qui a été reconnu pour faire croire aux gens que c'était en ls
train d'agrandir les globs.
Le problème est encore pire dans les cas suivants:
rm -- *.[ab]
S'il n'y a pas *.a
ni *.b
fichier dans le répertoire courant, alors vous pourriez finir par la suppression d' un fichier appelé *.[ab]
par erreur ( csh
, tcsh
et zsh
inscrira un pas de match erreur et ne serait pas appeler rm
(et fish
ne supporte pas les [...]
jokers)).
Si vous voulez passer un littéral *
à ls
, vous devez citer ce *
caractère d'une manière quelconque dans ls \*
ou ls '*'
ou ls "*"
. Dans les shells de type POSIX, le globbing peut être désactivé en utilisant set -o noglob
ou set -f
(ce dernier ne fonctionnant zsh
que dans sh
/ ksh
émulation).
¹ Alors qu’il (*/)#
a toujours été soutenu, il a d'abord été raccourci comme ..../
dans zsh-2.0 (et potentiellement auparavant), puis ****/
dans 2.1 avant d’obtenir sa forme définitive **/
dans 2.2 (début 1992).
find -name *
. Surtout avec des modèles plus complexes, s'il y a exactement une correspondance dans le répertoire actuel, les gens ne se rendront souvent pas compte qu'ils ne transmettent pas l'astérisque à find
.
*.[ab]
essayerait de supprimer tout ce qui se termine par .[ab]
. [
n'est pas spécial dans le poisson.
La commande par ls
défaut est ls .
: Liste toutes les entrées du répertoire en cours .
La commande ls *
signifie 'run ls sur le développement du *
motif shell'
Le *
modèle est traité par le shell et s'étend à toutes les entrées du répertoire en cours, à l'exception de celles commençant par un .
. Il ira un niveau de profondeur.
L’interprétation des *
motifs doubles ou triples dépend de la coque utilisée.
*
est un caractère générique qui correspond à 0 ou plusieurs caractères. Certains coquillages modernes se retrouveront dans des sous-répertoires en voyant le **
motif.
*
faire ajouter quelque chose, voir l'autre réponse expliquant la globstar. Il faut également préciser que cela n’a rien à voir avec les astérisques, il n’a jamais dépassé aucun de ces astérisques. Exécuter echo ls *
pour voir ce qui serait exécuté lorsque vous écrivez ls *
.
Vous pouvez démystifier l'ensemble du processus en tapant à la echo
place de la ls
première, pour voir en quoi la commande se développe:
$ echo *
Applications Downloads Documents tmp.html
Donc, dans ce cas, ls *
étend àls Applications Downloads Documents tmp.html
$ echo **
Applications Downloads Documents tmp.html
$ echo ***
Applications Downloads Documents tmp.html
Donc pas de changement. Cela suppose que vous l'utilisiez bash
comme coquille - la plupart des gens le sont, et différentes coquilles ont un comportement différent. Si vous utilisez ash
ou csh
ou ksh
ou zsh
, vous pouvez vous attendre à ce que les choses fonctionnent différemment. C'est le point d'avoir différentes coquilles.
Essayons donc quelque chose de différent (toujours avec bash
) afin que nous ayons une idée de ce que l’ *
opérateur globbing ( ) peut faire pour nous. Par exemple, nous pouvons filtrer par partie du nom:
$ echo D*
Downloads Documents
Et curieusement, une barre oblique de fin fait implicitement partie de tout nom de répertoire. Ainsi */
, seuls les répertoires (et les liens symboliques vers les répertoires) seront générés:
$ echo */
Applications/ Downloads/ Documents/
Et nous pouvons filtrer à plusieurs niveaux en plaçant des barres obliques au milieu:
$ echo D*/*/
Documents/Work/ /Documents/unfinished/
Comme le Downloads
répertoire ne contient aucun sous-répertoire, il ne se retrouve pas dans la sortie. Ceci est très utile pour simplement examiner les fichiers que vous voulez. J'utilise des commandes comme ça tout le temps:
$ ls -l /home/*/public_html/wp-config.php
Cela répertorie, le cas échéant, tous les wp-config.php
fichiers existant au niveau de base du public_html
répertoire de tout utilisateur . Ou peut-être pour être plus complet:
$ find /home/*/public_html/ -name wp-config.php
Ceci trouvera des wp-config.php
fichiers dans de tout utilisateur public_html
répertoires ou l' un de leurs sous - répertoires, mais il fonctionnera plus efficacement que juste find /home/ -name wp-config.php
parce qu'il n'examinera rien , mais les public_html
répertoires pour chacun des utilisateurs.
bash
votre shell" ← et que le globstar n'est pas activé. shopt -s globstar
et essayez à nouveau ...
set -x
commencer à imprimer la commande "réelle" exécutée à chaque fois (désactiver avec set +x
).
Dans certains shells, y compris bash 4.x avec l' globstar
option activée, **
effectuera un glob récurrent, des répertoires décroissants correspondants. Les astérisques supplémentaires ne modifient plus cette opération.
ksh93
et zsh
, bash
traverse les liens symboliques dans la récursion, ce qui est généralement indésirable.
Si vous voulez "plonger profondément", utilisez l'option ls -R (récursive), ou utilisez find, comme ceci:
find . -ls
"find" plongera au bas de l'arborescence (comme le fera 'ls -R'), et a beaucoup plus d'options, comme lister les répertoires (-type d), les fichiers uniquement (-type f) ou afficher les fichiers ayant d'autres caractéristiques (aucun utilisateur dans / etc / passwd, autorisations spécifiques, et beaucoup plus). "find" est également un peu plus sûr dans les scripts (en raison de règles de globalisation incohérentes entre les shells, ainsi que des échappements spéciaux pour les fichiers comportant des tirets, etc.).
La mise en forme générique de shell ne fonctionnera pas uniquement avec un astérisque '*' sur les fichiers de points. Pour lister uniquement les fichiers de points, utilisez:
ls .??*
Extra * n'ajoute pas de niveau de profondeur. Mais si vous essayez
ls */*/*
- vous obtiendrez la liste des sous-dossiers des sous-dossiers dans les dossiers du dossier actuel ...
*
ajoutera un niveau de profondeur.
bash
avec l’option globstar, le korn shell et zsh. Et peut-être d'autres, je suppose. unix.stackexchange.com/a/62665/14831
Ma prise principale est que echo ** / *. Ext sera généralement ...
Peut ou peut ne pas: lister un fichier .ext dans le répertoire courant
Peut ou peut ne pas: inclure les fichiers. *. Ext
Généralement, je préférerais que l'expression globale soit '** /' et que cela puisse donner une chaîne nulle (pas de sous-répertoire). Voici comment je convertis les expressions globales en entrée de programme. Bien sûr, je m'assure que des commentaires l'expliquent dans des exemples d'utilisation.