globstar: '** string *' não decrescente para subdiretórios '** / * string *'

3

Dado é um conjunto de arquivos em (sub) diretórios correspondentes a uma string como, por exemplo:

find -name 'string' | sort
./1/2/3/4/string
./1/2/3/string
./1/2/string
./1/string
./string

Por que usar globstar para corresponder aos arquivos como

ls **string
string

falha ao executar os diretórios, enquanto

ls **/string
1/2/3/4/string  1/2/3/string  1/2/string  1/string  string

é bem sucedido? Do meu entendimento da descrição nas páginas man , ela deveria estar combinando (sub) diretórios, não é?

Perguntas como essa geralmente são marcadas como duplicatas de "O resultado de ls *, ls ** e ls *** ", mas a resposta só lida com ls ** , que de fato recorre através de diretórios. Parece que um asterisco duplo seguido por uma string quebraria globstar .

Executando GNU bash v.4.4.19(1) em mint 19

De man bash

globstar

If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.

    
por Fiximan 10.10.2018 / 13:43

2 respostas

2

É assim que funciona no Ksh e no Zsh também.

$ mkdir -p a/b/cdir
$ touch    a/b/cfile
$ ksh -c 'set -o globstar; echo **c*'
**c*
$ zsh -c 'echo **c*'
zsh:1: no matches found: **c*

Em Correspondência de Padrões, o manual do Bash diz:

When the globstar shell option is enabled, and * is used in a filename expansion context, two adjacent *s used as a single pattern will match all files and zero or more directories and subdirectories.

Suponho que possa ser lido como significando que "um único padrão" é uma parte separada por barras, portanto, foo/**/bar o possui em um único padrão, mas **bar não.

Poderia ser mais claro, no entanto.

Uma barra após o padrão inteiro faz o padrão corresponder apenas aos diretórios:

$ echo **/c*/
a/b/cdir/
    
por 10.10.2018 / 14:26
1

Um * duplo decai para o efeito de um * quando não é limitado por (apenas) / :

$ ls *c
abc  ac  acc  bc  cc  dc

$ ls **c
abc  ac  acc  bc  cc  dc

Qualquer caractere inicial ou final que não seja um / torna a ** decay:

Isso ocorre simplesmente porque um nome de caminho (como nome de arquivo) pode não conter / .
Não é possível que um * seja expandido para um nome que contenha / . Um ** é um pouco semelhante, ele será expandido para strings contendo / somente quando sozinho ou delimitado por / (não qualquer outro caractere / string):

$ ls -d ./** | sort
./
./1
./1/2
./1/2/3
./1/2/3/4
./1/2/3/4/string
./1/2/3/string
./1/2/string
./1/string
./abc
./ac
./acc
./bc
./cc
./dc
./string

$ ls -d ./**c | sort 
./abc
./ac
./acc
./bc
./cc
./dc

$ ls -d ** | sort
1
1/2
1/2/3
1/2/3/4
1/2/3/4/string
1/2/3/string
1/2/string
1/string
abc
ac
acc
bc
cc
dc
string

$ ls -d **c | sort
abc
ac
acc
bc
cc
dc

$ ls -d **/ | sort
1/
1/2/
1/2/3/
1/2/3/4/

$ ls -d 1**/ | sort
1/
    
por 11.10.2018 / 12:45

Tags