O que `. []. Foo []` faz no bash? Por que corresponde a `..`?

16

Veja o seguinte:

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

Aparentemente, isso parece estar exagerando, mas eu não entendo como o resultado se aproxima. Do meu entendimento []é uma classe de personagem vazia. Seria intuitivo se

  • combinava apenas com a corda vazia; nesse caso, eu esperaria que o bash se reproduzisse por completo, já que nada corresponde a esse diretório, mas também a coisas como ..aliases(no primeiro exemplo),
  • ou nada; Nesse caso, eu esperaria que o bash também reproduz a string no total.

Isso ocorre com o GNU bash, versão 4.4.23 (1) - release.

Jonas Schäfer
fonte

Respostas:

25

O [inicia um conjunto. Um conjunto é encerrado por ]. Mas há uma maneira de ter ]como parte do conjunto, e isso é especificar ]como o primeiro caractere. Como um conjunto vazio não faz nenhum sentido, isso não é ambíguo.

Portanto, seus exemplos são basicamente um ponto seguido de um conjunto que contém um ponto; portanto, ele corresponde a dois pontos.

Os exemplos posteriores não encontram nenhum arquivo e, portanto, são retornados literalmente.

RalfFriedl
fonte
4

Somente seqüências de caracteres citadas não estão sujeitas a globbing:

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

Mas strings sem aspas estão sujeitas a globbing. Uma sequência não cotada que contém um *ou um ?ou (válido) [](expressão entre colchetes) será modificada pela lista de arquivos que correspondem a ela. Da mesma maneira que a *se transformará em todos os arquivos no diretório correspondente e a ?corresponderá a arquivos de apenas um caractere, a (válido) []corresponderá aos arquivos com os caracteres dentro dos colchetes. Um ponto é um caractere válido:

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

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

Para poder corresponder a ], deve ser o primeiro caractere entre colchetes:

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

Uma expressão de colchete vazio não faz sentido (e não é expandida):

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

É por isso que isso funciona:

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

Para [a idéia é semelhante:

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

mas poderia estar em qualquer posição em uma expressão entre colchetes:

$ 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

A string que você postou .[].foo[]corresponderá a um ponto seguido por a ], a ., a f, a oou a [. É similar à:

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

E corresponderá da seguinte forma:

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

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

Observe que a entrada do diretório ..não precisa ser criada, pois existe dentro de cada diretório por padrão. Mas um ponto simples .não será correspondido por um globo, pois precisa ser correspondido explicitamente (usando realmente um ponto).

Mas isso não corresponderá, ..aliasespois a expressão entre colchetes corresponderá apenas a um caractere. Para combinar vários caracteres, você precisa usar um *(qualquer coisa):

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

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