Procura arquivos por uma string e, se encontrada, verifica se existe um arquivo com nome pareado no mesmo diretório

3

Eu tenho muitos arquivos diferentes com a mesma terminação .ft1 que pode ou não conter uma palavra específica special . Para os arquivos que contêm essa palavra, desejo verificar se existe outro arquivo com uma final diferente .log nesse diretório.

O que eu tenho até agora é isso:

find . -name "*.ft1" -exec grep -l "special" {} \; -execdir ls *log \;

No entanto, isso me causa um erro toda vez que o ls é executado:

ls: cannot access *log: No such file or directory

Mas eu sei que existem tais arquivos nesse diretório. Eu também tentei escapar da estrela, então a expressão se torna -execdir ls \*log \; , mas o erro persiste.

Eu também dei uma olhada em isso

Como faço para que isso se comporte corretamente? Pontos de bônus para uma solução que lista apenas .log arquivos com o mesmo nome, como os arquivos .ft1 encontrados.

    
por tschoppi 13.11.2015 / 20:51

5 respostas

4

Seu problema é que você precisa de um shell para interpretar o *.log glob. Então você precisa de -execdir para invocar um shell. O snippet a seguir também abordará seu requisito de "mesmo nome"

find . -name "*.ft1" -exec grep -l "special" {} \; \
-execdir bash -c 'x=$1; x=${x%.txt}; ls "$x".log' bash {} \;
    
por 13.11.2015 / 22:36
4

Supondo que não haja espaços em seus nomes de arquivos (e que seu coração não esteja definido em usar find ), isso deve funcionar:

for file in *.ft1; do
   if grep -q 'special' ${file}; then
      ls -l ${file%.ft1}.log 2> /dev/null
   fi
done

Ele usa manipulação de string bash para extrair .ft1 do final. Eu poderia usar ${file/ft1/log} , mas isso também corresponderia a qualquer nome de arquivo que tivesse ft1 antes da extensão.

Eu redireciono stderr de ls para ocultar tentativas de ls dos arquivos .log que não existem.

    
por 13.11.2015 / 21:13
3

Usando grep -r e awk

grep -rl 'special' *.ft1 | awk '{sub(/\.ft1$/,"");system("sh -c \"[ -f "$0".log ] && echo \\"["$0".log\\"] exists for ["$0".ft1]\"")}'

ou com a saída de ls

grep -rl 'special' *.ft1 | awk '{sub(/\.ft1$/,"");system("sh -c \"[ -f "$0".log ] && ls "$0".log \"")}'

Exemplo

% grep -rl 'special' *.ft1 | awk '{sub(/\.ft1$/,"");system("sh -c \"[ -f "$0".log ] && echo \\"["$0".log\\"] exists for ["$0".ft1]\"")}'
[one.log] exists for [one.ft1]

% grep -rl 'special' *.ft1 | awk '{sub(/\.ft1$/,"");system("sh -c \"[ -f "$0".log ] && ls "$0".log \"")}'
one.log

% ls -laog                        
total 100
drwxrwx--x   4  4096 Nov 13 22:03 .
drwxr-xr-x 272 86016 Nov 13 22:03 ..
drwxrwxr-x   2  4096 Nov 13 20:37 bar
drwxrwxr-x   2  4096 Nov 13 20:37 foo
-rw-rw-r--   1     8 Nov 13 21:55 one.ft1
-rw-rw-r--   1     0 Nov 13 21:54 one.log
-rw-rw-r--   1     0 Nov 13 21:54 three.ft1
-rw-rw-r--   1     0 Nov 13 21:54 two.ft1
-rw-rw-r--   1     0 Nov 13 21:54 two.log

% cat one.ft1
special

% cat two.ft1
    
por 13.11.2015 / 22:05
3

Uma solução muito simples com find , awk e bash . Idéia básica, encontre todos os arquivos com ft1 extension, dê a eles como lista de argumentos de linha de comando para grep , que gera uma lista de arquivos com strings "especiais", e canalize essa saída para awk que será string a extensão ft1 e substitua-a pela extensão "log". Finalmente, dê a ele o bash, que irá verificar se existe um arquivo de log com a mesma extensão

find . -type f -iname "*.ft1"  -exec grep "special" {} + | awk -F':' '{gsub(/\.ft1/,"");print $1".log"}'  | xargs -I {} bash -c " [ -f {}  ] && echo {} exists"

Pequena demonstração

xieerqi@eagle:~/testdir2$ ls
one.ft1  one.log  three.ft1  two.ft1  two.log
xieerqi@eagle:~/testdir2$ find . -type f -iname "*.ft1"  -exec grep "special" {} + | awk -F':' '{gsub(/\.ft1/,"");print $1".log"}'  | xargs -I {} bash -c " [ -f {}  ] && echo {} exists"
./two.log exists
./one.log exists
    
por 13.11.2015 / 21:47
1

Aqui está uma alternativa zsh :

print -rl -- **/*.ft1(.e_'grep -q special $REPLY && REPLY=$REPLY:r.log && [[ -f $REPLY ]]'_)

Isso irá procurar recursivamente por .ft1 arquivos contendo essa cadeia e imprimir apenas os arquivos .log correspondentes. Se você deseja imprimir todos os arquivos .ft1 que contêm a string special e os arquivos .log correspondentes (se houver), basta substituir grep -q por -l .
Veja aqui como funciona (este tem uma condição adicional - a parte grep , o resto é o mesmo).

    
por 13.04.2017 / 14:36

Tags