Extrai o caminho do diretório que contém o arquivo com a string correspondente

2

Eu tenho vários subdiretórios em vários níveis que contêm um resultado de arquivo.out

./dir1/results.out
./dir2/dir21/results.out
./dir3/dir31/dir311/results.out

Agora, preciso pesquisar string1 in results.out e extrair o caminho do diretório daqueles results.out que contêm string1 , pois preciso mover esses subdiretórios para outro local. Por exemplo, posso obter o caminho do arquivo usando o seguinte código

for i in $(find . -type f -name "results.out);
do
grep -l "string1" $i
done

Como modificar o código acima para obter apenas o caminho do diretório?

    
por WanderingMind 21.07.2016 / 00:23

5 respostas

5

Se você tiver o GNU find , poderá imprimir o caminho usando o especificador de formato %h

    %h     Leading directories of file's name (all but the last ele‐
           ment).  If the file name contains no slashes (since it is
           in  the  current  directory)  the %h specifier expands to
           ".".

Então, por exemplo, você poderia fazer

find . -name 'results.out' -exec grep -q 'string1' {} \; -printf '%h\n'
    
por 21.07.2016 / 00:54
4

com zsh :

print -rl ./**/results.out(.e_'grep -q string $REPLY'_:h)

isso pesquisa recursivamente arquivos regulares ( . ) chamados results.out , executa grep -q ... em cada um deles e, se esse e avaliar true , ele imprime apenas h ead do caminho (o caminho sem o último elemento).

Outra maneira com find e sh , usando a expansão de parâmetro para extrair a cabeça:

find . -type f -name results.out -exec grep -q string {} \; \
-exec sh -c 'printf %s\n "${0%/*}"' {} \;
    
por 21.07.2016 / 02:15
1
for i in $(find . -type f -name "results.out);
do
grep -l "string1" $i ; exitcode=${?}
if [ ${exitcode} -eq 0 ]  # string1 is found in file $i
then
   path=${i%/*}
   echo ${path}
fi
done
    
por 21.07.2016 / 00:47
1

Em um sistema GNU:

 find . -depth -type f -name results.out -exec grep -lZ string1 {} + |
   xargs -r0 dirname -z |
   xargs -r0 mv -t /dest/dir

Ou:

 find . -depth -type f -name results.out -exec grep -lZ string1 {} + |
   LC_ALL=C sed -z 's|/[^/]*$||' |
   xargs -r0 mv -t /dest/dir

O -depth é igual a ./A/results.out e ./A/B/results.out , ./A/B é movido para /dest/dir/B antes de ./A ser movido para /dest/dir/A .

    
por 03.08.2016 / 13:26
0

Supondo que entendi corretamente, você quer fazer exatamente isso:

find . -type f -name "results.out" -exec grep -l "string1" {} \; | xargs dirname

A primeira parte obtém os nomes dos arquivos correspondentes, então xargs passa aqueles como um argumento para o programa dirname que 'remove' o nome do arquivo do caminho

    
por 21.07.2016 / 00:47