Como posso listar os nomes dos diretórios que contêm nomes de arquivos correspondentes a um padrão?

2

Dado um diretório X que contém vários subdiretórios e arquivos, gostaria de listar os nomes dos diretórios filhos imediatos de X que (direta ou indiretamente) contêm nomes de arquivos correspondentes à regex ^rf.*\.img$ .

Como isso pode ser alcançado no OS X?

    
por blz 16.11.2015 / 12:49

5 respostas

3

Com o GNU find , você pode testar cada diretório:

for i in "$dir"/*/
do
    test -n "$(find "$i" -type f -regex '.*/test[^/]*' -print -quit)" \
       && echo "$i"
done

Isso pesquisa cada diretório por um arquivo que começa com test e imprime o diretório, se for encontrado.

Algumas coisas a serem observadas:

  1. Estou ignorando os subdiretórios que começam com . ; Se precisarem ser considerados, verifique as perguntas frequentes sobre Bash sobre como incluí-las sem também capturar . e .. .
  2. Saímos find cedo, usando -quit quando recebemos uma correspondência. Isso pode economizar tempo em grandes árvores de sistema de arquivos.
  3. O teste -regex corresponde a todo o nome de caminho considerado por find , portanto, se quisermos corresponder apenas ao nome da base, precisamos ter cuidado ao corresponder / . Podemos combinar em padrões curinga sem essa restrição (e sem exigir a descoberta do GNU), usando -filename .
  4. Você pode usar -iregex em vez de -regex para uma correspondência sem distinção entre maiúsculas e minúsculas.
  5. Você pode selecionar a sintaxe regex usando a opção -regextype .

Para o padrão específico na pergunta, podemos usar curingas, por isso, torna-se:

for i in "$dir"/*/
do
    test -n "$(find "$i" -type f -name 'rf*.img' -print -quit)" && echo "$i"
done
    
por 16.11.2015 / 13:15
2

Com zsh (supondo que você já esteja em X ):

typeset -U subdirs
subdirs=(*/**/rf*.img(.e_'REPLY=${REPLY%%/*}'_))
print -rl -- "${subdirs[@]}"

Aqui */**/rf*.img globs para todos os arquivos rf*.img em todos os subdiretórios, os qualificadores glob . e e selecionam apenas arquivos regulares e salvam apenas o primeiro componente do caminho em uma matriz definida inicialmente como uma matriz com elementos exclusivos (sem duplicações). Em seguida, ele imprime cada elemento da matriz.

    
por 16.11.2015 / 14:44
1

Você pode obter uma lista usando find e canalizar isso através de grep :

(cd X && find . -type d -maxdepth 1 | sed -e 's,^./,,' | grep -E '^rf.*\.img$' )

Eu usei um subshell para obter apenas os nomes dentro de X ; caso contrário, seria necessário considerar o caminho em find .

Se você quiser subdiretórios recursivamente, poderá omitir a opção -maxdepth 1 . Mas então isso significa que você teria que ajustar a expressão regular, por exemplo,

(cd X && find . -type d | sed -e 's,^./,,' | grep -E '^(.*/)?rf.*\.img$' )

e, nesse caso, o comando sed é redundante (mas inofensivo).

    
por 16.11.2015 / 12:53
1

Não use grep nem ls , mas find :

find . -name 'rf*.img'

O GNU find tem uma opção para imprimir apenas o diretório ( -printf "%h\n" ), mas no seu caso, isso não é uma opção.

Você pode fazer algo como:

find . -name 'rf*.img' | sed 's:/[^/]*$::'

Se você quiser apenas o primeiro diretório, talvez algo como:

find . -name 'rf*.img' -exec dirname {} \; | sed 's:./\([^/]*\).*::'
    
por 16.11.2015 / 13:02
0

Use perl e seus grep e glob .

#!/usr/bin/env perl
use strict;
use warnings;

my @file_list = grep { /^rf.*\.img$/ } glob "*";
print join ( "\n", @file_list );

Ou como um verso:

perl -e 'print join ( "\n", grep { /^rf.*\.img$/ } glob "*" )'

Nota - glob faz expansões curinga no estilo de shell, portanto você pode glob "*/*/name/*" ou similar. Se você precisar de uma profundidade de recursão arbitrária, convém usar File::Find :

#!/usr/bin/env perl
use strict;
use warnings;

use File::Find;

sub print_match {
    #Default match is against $_ which is filename. 
    #can match $File::Find::name for full name.
    #or $File::Find::dir
    print if  /^rf.*\.img$/;
}

find ( \&print_match, "/path/to/search" );

Como um verso de novo:

perl -MFile::Find -e 'find ( sub { print if  /^rf.*\.img$/ }, "/my/path/to/search" );'
    
por 16.11.2015 / 18:06

Tags