Cosa fa `. []. Foo []` in bash? Perché corrisponde a ".."?


16

Guarda quanto segue:

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

Apparentemente sembra che stia traballando qualcosa, ma non capisco come il risultato si unisca. Dalla mia comprensione []è una classe di caratteri vuota. Sarebbe intuitivo se

  • corrispondeva solo alla stringa vuota; in questo caso, mi aspetto che bash si riproduca nella sua interezza poiché nulla corrisponde a questa directory, ma corrisponde anche a cose come ..aliases(nel primo esempio),
  • o niente affatto; in questo caso, mi aspetto che anche bash riproduca la stringa in totale.

Questo è con GNU bash, versione 4.4.23 (1).

Risposte:


25

Il [inizia un set. Un set termina con ]. Ma c'è un modo per avere ]come parte del set, e cioè specificare ]come primo carattere. Poiché un set vuoto non ha alcun senso, questo non è ambiguo.

Quindi i tuoi esempi sono fondamentalmente tutti un punto seguito da un set che contiene un punto, quindi corrisponde a due punti.

Gli esempi successivi non trovano alcun file e vengono quindi restituiti alla lettera.


4

Solo le stringhe tra virgolette non sono soggette a oscillazioni:

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

Ma le stringhe non quotate sono soggette a strappi. Una stringa non quotata che contiene un *o un ?o (valido) [](espressione di parentesi) verrà modificata dall'elenco dei file che la corrispondono. Allo stesso modo in cui a *si trasformerà in tutti i file nella directory corrispondente e a ?corrisponderà a file di un solo carattere, a (valido) []abbinerà i file con i caratteri tra parentesi. Un punto è un carattere valido:

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

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

Per poter abbinare un ]dovrebbe essere il primo carattere tra parentesi:

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

Un'espressione di parentesi vuota non ha senso (e non è espansa):

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

Ecco perché funziona:

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

Perché [l'idea è simile:

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

ma potrebbe trovarsi in qualsiasi posizione in un'espressione di parentesi:

$ 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 stringa che hai pubblicato .[].foo[]corrisponderà a un punto seguito da a ], a ., a f, a oo a [. È simile a:

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

E corrisponderà come segue:

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

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

Si noti che ..non è necessario creare la voce della directory in quanto esiste all'interno di ogni directory per impostazione predefinita. Ma un punto semplice .non verrà abbinato da un glob in quanto deve essere abbinato esplicitamente (utilizzando effettivamente un punto).

Ma ciò non corrisponderà ..aliasespoiché l'espressione parentesi corrisponderà a un solo carattere. Per abbinare più personaggi devi usare un *(qualsiasi cosa):

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

$ echo .[].aliases[]*
.. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.