Que fait `. []. Foo []` dans bash? Pourquoi correspond-il à «..»?

16

Regardez ce qui suit:

$ echo .[].aliases[]
..
$ echo .[].foo[]
..
$ echo .[].[]
..
$ echo .[].xyz[]
..
$ echo .xyz[].xyz[]
.xyz[].xyz[]
$ echo .xyz[].[]
.xyz[].[]

Apparemment, cela semble globuler quelque chose, mais je ne comprends pas comment le résultat se conjugue. De ma compréhension []est une classe de personnage vide. Ce serait intuitif si

  • il ne correspondait qu'à la chaîne vide; dans ce cas, je m'attendrais à ce que bash se reproduise dans son intégralité car rien ne lui correspond dans ce répertoire, mais aussi des choses comme ..aliases(dans le premier exemple),
  • ou rien du tout; dans ce cas, je m'attends à ce que bash reproduise également la chaîne au total.

C'est avec GNU bash, version 4.4.23 (1) -release.

Jonas Schäfer
la source

Réponses:

25

Le [démarre un ensemble. Un ensemble se termine par ]. Mais il existe un moyen d'avoir ]comme partie de l'ensemble, et c'est de spécifier le ]comme premier caractère. Comme un ensemble vide n'a aucun sens, ce n'est pas ambigu.

Donc, vos exemples sont essentiellement tous un point suivi d'un ensemble qui contient un point, donc il correspond à deux points.

Les exemples ultérieurs ne trouvent aucun fichier et sont donc retournés textuellement.

RalfFriedl
la source
4

Seules les chaînes entre guillemets ne sont pas soumises à la globalisation:

$ echo ".[].aliases[]"
.[].aliases[]

Mais les chaînes non citées sont sujettes à la globalisation. Une chaîne sans guillemets qui contient un *ou un ?ou (valide) [](expression entre crochets) sera modifiée par la liste des fichiers qui lui correspondent. De la même manière qu'un a *se transformera en tous les fichiers du répertoire correspondant et un ?correspondra aux fichiers d'un seul caractère, un (valide) []fera correspondre les fichiers avec les caractères entre crochets. Un point est un caractère valide:

$ echo a[.]b
a[.]b

$ touch "a.b"
$ echo a[.]b
a.b

Pour pouvoir faire correspondre un, ]il doit être le premier caractère entre crochets:

$ touch "a]b"
$ ls a[]]b
a]b

Une expression de parenthèse vide n'a aucun sens (et n'est pas développée):

$ touch ab
$ ls a[]b
ls: cannot access 'a[]b': No such file or directory

Voilà pourquoi cela fonctionne:

$ touch a]c abc afc azc a:c a?c aoc 
$ ls a[]bfz:?]c
abc  a:c  a?c  a]c  afc  azc

Car [l'idée est similaire:

$ touch a[c
$ ls a[[]c
a[c

mais il pourrait être à n'importe quelle position dans une expression entre crochets:

$ ls a[]bf[z:?]c
abc  a:c  a?c  a[c  a]c  afc  azc

$ ls a[]bfz:?[]c
abc  a:c  a?c  a[c  a]c  afc  azc

La chaîne que vous avez publiée .[].foo[]correspondra à un point suivi de a ], a ., a f, a oou a [. C'est similaire à:

$ echo a[].foo[]c
a[c a]c afc aoc

Et cela correspondra comme suit:

$ touch .] .f .o .[ .a .b .z

$ echo .[].foo[]
.. .[ .] .f .o

Notez que l'entrée de répertoire ..n'a pas besoin d'être créée car elle existe dans chaque répertoire par défaut. Mais un simple point .ne sera pas mis en correspondance par un glob car il doit être mis en correspondance explicitement (en utilisant réellement un point).

Mais cela ne correspondra pas ..aliasescar l'expression du crochet ne correspondra qu'à un seul caractère. Pour faire correspondre plusieurs caractères, vous devez utiliser un *(n'importe quoi):

$ touch ..a ..l ..i ..aliases ..alias ..ali
$ echo .[].aliases[]
.. .[ .] .a

$ echo .[].aliases[]*
.. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l
Isaac
la source