grep comando para procurar um padrão em vários arquivos e listar os arquivos ordenados por data

1

Eu tenho um requisito para procurar um padrão em vários arquivos e obter o arquivo mais recente para processamento adicional. Eu estou tentando fazer isso em um script de shell. Eu estava tentando fazer da seguinte forma

file='grep -lh <pattern> <file_name> | tail -1'

Mas o grep está listando os arquivos como em ls e não como ls -lrt . Eu tentei o seguinte comando

ls -lrt 'grep -l <pattern> <file name>'

Mas não consigo incorporar esse comando no script de shell. Qualquer ajuda é apreciada.

Obrigado

    
por Dennis Williamson 23.10.2009 / 23:53

5 respostas

1

Isso é muito mais rápido. Enquanto o outro responde grep all os arquivos, ele pesquisa primeiro os mais novos e pára assim que encontra o padrão.

Este one-liner captura o resultado em uma variável:

file=$(while read file; do grep pattern "$file" >/dev/null;[[ $? ]]; then echo "$file"; break; fi; done < <(find $startdir -maxdepth 1 -type f -printf "%T@:%p\n"|sort -nr|cut -d: -f2-))

Aqui está uma versão do script Bash que é mais fácil de ler:

#!/bin/bash
while read file
do
    grep pattern "$file" > /dev/null
    if [[ $? ]]
    then
        echo "$file"
        break
    fi
done < <(find $startdir -maxdepth 1 -type f -printf "%T@:%p\n" |
            sort -nr |
            cut -d: -f2-)
    
por 24.10.2009 / 03:14
0

você pode canalizar a saída do grep para xargs para usar o ls -lrt antes de canalizar através da cauda

    
por 24.10.2009 / 00:12
0

Isso deve ser feito:

ls -lrt|awk '{print $9}'|xargs -n1 grep <string>|tail -n1|awk '{print $1}'

Você pode precisar alterar quais variáveis no awk serão impressas, dependendo da sua implementação de ls e grep.

Basicamente, classifique os arquivos primeiro, depois procure pela string, depois pegue o último resultado.

    
por 24.10.2009 / 00:14
0
bluerain ~ # ls -lrt 'grep -l a *.sh '
    -rwxr-xr-x 1 root root 315 2007-01-20 17:43 twopass.sh
    -rwxr-xr-x 1 root root  86 2007-04-21 16:23 hd_down.sh
    -rwxr-xr-x 1 root root 245 2009-09-10 19:47 pspenc.sh
    -rwxr--r-- 1 root root  95 2009-09-10 19:50 psp2.sh 
bluerain ~ # kk='grep -l a *.sh' 
bluerain ~ # bb=' ls -rt $kk | tail -1' 
bluerain ~ # echo $bb psp2.sh 
bluerain ~ # echo $kk hd_down.sh psp2.sh pspenc.sh twopass.sh

use o seguinte:

tempvar='grep -l <pattern> *(for all files in the directory)'
file='ls -rt $tempvar | tail 1'
    
por 24.10.2009 / 00:18
0

No seu primeiro exemplo, grep não deve reordenar os nomes de arquivos que você passa para ele. Se você os estiver passando explicitamente, ele imprimirá a saída na mesma ordem que a lista de arquivos que você passa. No entanto, se você está passando um caractere curinga, está correto que seu shell expandirá esse caractere curinga na ordem lexical (que é basicamente o que ls usa como padrão).

Depois de analisar as outras sugestões, apresento o seguinte:

file='ls -t --quoting-style=shell "dir" | xargs grep -l "regex" | head -n 1'

Acho que isso atende aos seus requisitos e aborda as preocupações levantadas por outras pessoas da seguinte forma:

  1. Você pode usar ls -t sem -l , portanto não há necessidade de analisar a saída de ls -l com awk ou cut apenas para obter o nome do arquivo.
  2. Não inverta a ordem de classificação de ls . Usar ls -t coloca os arquivos mais novos em primeiro lugar, e pegar o primeiro com head causará um curto-circuito no pipeline assim que o primeiro arquivo correspondente for encontrado (assim você procura a lista mínima de arquivos necessários para encontrar uma correspondência).
  3. O piping para xargs efetivamente permite pesquisar um número ilimitado de arquivos sem executar o comprimento máximo da linha de comando, e faz isso sem loop.
  4. O uso de ls --quoting-style=shell fornece nomes de arquivos com aspas simples, conforme necessário, portanto, nomes de arquivos com espaços incorporados ou caracteres de controle são manipulados corretamente.

Por favor, note que --quoting-style é uma extensão GNU e não é provável que funcione com um não-GNU ls . Você deve estar bem no Linux. O seguinte é mais portátil, mas adiciona uma chamada a sed para citar os nomes dos arquivos, portanto, há um pouco mais de sobrecarga:

file='ls -t "dir" | sed 's/\(.*\)/""/' | xargs grep -l "regex" | head -n 1'
    
por 24.10.2009 / 06:18

Tags