grep que apenas retorna caminhos de diretório [closed]

0

Estou usando o grep para pesquisar em um diretório grande, o problema que estou tendo é que precisei apenas dos diretórios que atendem à expressão regular. Eu não preciso dos nomes dos arquivos.

O comando grep que estou usando é.

grep -Erin "RegEx" * > outputfile.txt
    
por C Smith 24.09.2018 / 19:44

6 respostas

1

Com base no que @RalfFriedl disse, se você quer apenas o nome do diretório onde o arquivo que corresponde à expressão regular está localizado, você pode usar o dirname. Se houver vários arquivos nesse diretório, você poderá recolher sua saída para uma lista única classificada usando a classificação. Algo como o seguinte:

dirname $(grep -Eril "RegEx" *) | sort -u
    
por 24.09.2018 / 19:57
0

O Grep não tem uma opção para isso.

Se você não deseja os nomes dos arquivos, por que você usa a opção -n para números de linha?

Existe uma opção para listar os nomes dos arquivos correspondentes:

-l, --files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.

Você pode usar sed para excluir a última parte do nome do arquivo e manter apenas a parte do diretório. Se você quiser apenas que cada diretório seja listado uma vez, poderá executar a saída por meio de sort -u .

    
por 24.09.2018 / 19:54
0

Considere o uso do comando find .

find . -type d -regextype posix-extended -regex 'RegEx'

Procura no diretório atual, por coisas do tipo diretório, nomes de caminho correspondentes usando posix-extended (o mesmo que grep -E).

    
por 24.09.2018 / 20:00
0

Use a opção -l grep e pós-processe com sed :

grep -rilE "RegEx" * |sed 's![^/]*$!!' > outputfile.txt

A expressão sed remove (do $ final da linha) qualquer caractere que não seja uma barra, deixando apenas o (s) nome (s) do diretório.

    
por 24.09.2018 / 20:02
0
# usage: dgrep regex dir
dgrep(){
        find "$2" -type d -print0 | xargs -0 sh -c '
                rex=$1; shift
                for d; do grep -sq "$rex" "$d"/* "$d"/.[!.]* && echo "$d"; done
        ' sh "$1"
}

Diferentemente das soluções grep -rl + sed , isso varrerá apenas os arquivos no diretório até que uma primeira correspondência seja encontrada - dependendo de seus dados, isso pode acelerar bastante as coisas.

Sinta-se à vontade para adicionar suas opções do grep após -sq ; um script onde eles seriam passados na linha de comando é possível, mas complicaria tudo com pouco benefício.

    
por 24.09.2018 / 20:28
0

Em um sistema GNU:

grep -ErliZ "RegEx" . |
  LC_ALL=C sed -z 's|/[^/]*$||' |
  LC_ALL=C sort -zu |
  tr '
find . -type f -print0 | LC_ALL=C gawk -v RS='
grep -ErliZ "RegEx" . |
  LC_ALL=C sed -z 's|/[^/]*$||' |
  LC_ALL=C sort -zu |
  tr '
find . -type f -print0 | LC_ALL=C gawk -v RS='%pre%' '
  BEGIN{while ((getline < "/dev/stdin") > 0) ARGV[ARGC++] = $0}
  FNR == 1 {dir = FILENAME; sub("/[^/]*$", ""); if (dir in found) nextfile}
  /RegEx/ {found[dir]; print dir; nextfile}'
' '\n'
' ' BEGIN{while ((getline < "/dev/stdin") > 0) ARGV[ARGC++] = $0} FNR == 1 {dir = FILENAME; sub("/[^/]*$", ""); if (dir in found) nextfile} /RegEx/ {found[dir]; print dir; nextfile}'
' '\n'

Isso não é o ideal, pois ele procura RegEx em todos os arquivos em um diretório, mesmo depois que uma correspondência já foi encontrada.

Para evitar isso e ainda evitar a execução de um grep por diretório, com o GNU awk , você poderia fazer:

%pre%

Estamos usando LC_ALL=C , portanto, sub("/[^/]*$", "") pode remover com segurança a parte do nome do arquivo, mas isso significa que a decodificação do texto nos arquivos não é feita de acordo com o mapa de caracteres do local. Se você souber que todos os caminhos de arquivo são texto válido na localidade atual, você poderá removê-lo. Ou você pode adicionar um -name '*' a find para ignorar nomes de arquivos que contenham seqüências de bytes que não formam caracteres válidos no idioma.

    
por 24.09.2018 / 21:34