Encontre a última ocorrência de uma string em um determinado tipo de arquivo em todos os subdiretórios

3

Eu tenho vários subdiretórios, cada um com diferentes profundidades. Eu preciso procurar a última ocorrência de uma string em um tipo de arquivo específico (digamos *.out ). Como posso conseguir isso?

Eu tentei:

grep -r 'string' **/*.out | tail -1

Mas isso me dá apenas a última string do último arquivo.

    
por WanderingMind 07.05.2015 / 19:39

4 respostas

1

Vou usar algo como:

for i in 'find . -name "*.out" -type f';
do
grep -l 'string' $i
grep 'string' $i|tail -1
done

Com o primeiro grep você terá o nome do arquivo e abaixo (segundo grep) o conteúdo.

Isso funciona desde que os nomes dos arquivos não contenham espaços em branco ou \[*? . Veja resposta do cuonglm para uma solução robusta.

    
por 07.05.2015 / 19:46
2

Suponha que você esteja no diretório pai dos subdiretórios:

find . -type f -name '*.out' -exec sh -c '
  for f do
    grep "string" /dev/null "$f" | tail -n 1
  done
' sh {} +
    
por 07.05.2015 / 19:53
1

Com zsh em um sistema GNU:

for f (**/*.out(.)) tac < $f | grep --label=$f -m1 string
    
por 08.05.2015 / 00:34
1

Com as ferramentas gnu , você pode usar uma única chamada de gawk :

awk '/pattern/{l=$0} ENDFILE{if (l) {print FILENAME ":" l; l=""}}' **/*.out

(se as correspondências de linha armazenarem em l ; no final de cada arquivo, se l não estiver vazio, nome do arquivo de impressão e l , então redefinir l )

ou sed :

sed -ns '/pattern/h;${x;//{F;p}}' **/*.out

(se a linha corresponder, copie para h old space; se la $ t line, e x change mantenha espaço w. pattern space; se corresponder, p rint F ile name e line)
embora a saída seja diferente - o nome do arquivo e a última linha correspondente correspondem a linhas separadas - mas se canalizado para outro sed , por exemplo,

sed -ns '/pattern/h;${x;//{F;p}}' **/*.out |sed '$!N;s/\n/:/'

ele imitará grep output 1 .
O acima assume bash (v. 4 com shopt -s globstar ) ou zsh . Para incluir arquivos ocultos, adicione shopt -s dotglob ( bash ) ou setopt dotglob ( zsh ).

1: desde que nenhum desses nomes de arquivo contenha caracteres de nova linha.

    
por 08.05.2015 / 00:11