Glob recursiva?


80

Eu gostaria de escrever algo como isto:

$ ls **.py

para obter todos os nomes de arquivos .py, percorrendo recursivamente uma hierarquia de diretórios.

Mesmo se houver arquivos .py para encontrar, o shell (bash) fornecerá esta saída:

ls: cannot access **.py: No such file or directory

Alguma maneira de fazer o que eu quero?

Edição: Gostaria de especificar que não estou interessado no caso específico de ls, mas a pergunta é sobre a sintaxe glob.

Respostas:


98

Para fazer globs recursivos no bash, você precisa do globstarrecurso do bash versão 4 ou superior.

Na página de manual do 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.

Para o seu padrão de exemplo:

shopt -s globstar
ls **/*.py

2
Eu recomendo também permitirnullglob
glenn jackman 4/12

6
@glennjackman Mas antes de ativar nullglob, eu recomendo fortemente a leitura após os avisos .
Serge Stroobandt

2
^ Os avisos foram movidos para aqui .
usandfriends

1
Com o bash 3.2, wc -l {**,.}/*.pyfunciona muito bem
Raphael

@ Rafael Verifiquei as notas de versão e definitivamente diz que foi introduzido na 4.0. Talvez sua distribuição tenha suportado um patch para isso? O IIRC RHEL 5 havia suportado alguns recursos. Também digno de nota, tem sido 9 anos desde o bash 4 foi lançado ...
jordanm

10
find . -name '*.py'

** não faz nada além de um único *, ambos operam no diretório atual


Interessante. No entanto, estou mais focado na sintaxe glob por si só, porque tenho que usá-lo em um arquivo de configuração (incluir diretiva). Não preciso de uma lista de arquivos.
Paolo

2
@ Doug O'Neal, isso não é mais verdade. festa já copiado esse recurso zsh (embora ele adotou uma sintaxe mais próxima à de ksh93 e como ksh, não suporta eliminatórias englobamento do zsh ainda que limita sua utilidade)
Stéphane Chazelas

Você pode fazer muitas coisas findse não tiver o bash 4. Exemplos: yourcommand `find . -name '*.py'`(observe os backticks); find . -name '*.py' -exec yourcommand {} \;.
Mars

5

Desde o Bash 4 (incluindo também o zsh) , foi adicionada uma nova opção de globbing ( globstar), que trata o padrão de maneira **diferente quando está definido.

Ele corresponde ao padrão curinga e retorna os nomes de arquivos e diretórios correspondentes, substituindo o padrão curinga no comando pelos itens correspondentes.

Normalmente, quando você usa **, ele funciona de maneira semelhante a *, mas repete todos os diretórios recursivamente (como um loop).

Para ver se está ativado, verifique-o shopt globstar(em scripts, use shopt -q globstar).

O exemplo **.pyfuncionaria apenas para o diretório atual, pois não retorna uma lista de diretórios que podem ser recorrentes; é por isso que você precisa usar vários curingas no nível de diretório **/*.py, para que possa ir mais fundo.

Por favor em encontrar SO alguns testes de sintaxe que fiz para encontrar todos os arquivos de forma recursiva.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.