Assistente de linha de comando: espaços em nomes de arquivos com find | grep | xargs

5

Eu preciso de uma maneira de executar o grep em uma lista de arquivos que podem conter espaços no nome do arquivo. Em uma lista de arquivos sem espaços, é bastante simples e fácil. Além disso, eu sei como lidar com espaços nos nomes de arquivos para encontrar e xargs . Estou apenas procurando uma maneira de usar grep com o comando -print0.

Estou procurando texto dentro do arquivo, não no nome do arquivo ...

Isso lista todos os arquivos:

find * -print 0 | xargs -0 -i{} echo {}

mas digamos que tenho que fazer um grep (ou algum outro comando) no meio.

Isto lista os arquivos que contêm "howdy doody" dentro do arquivo:

find * | xargs grep -l "howdy doody" | xargs -i{} echo {}

Isso não funciona, grep não sabe como reconhecer linhas terminadas em null. Eu senti falta de alguma coisa na man page do grep ?

find * -print0 | xargs grep -l "howdy doody" | xargs -0 -i{} echo {}
    
por Roy Rico 07.12.2009 / 21:28

2 respostas

15

Você está procurando "howdy doody" no nome do arquivo ou no arquivo?

# find files with "howdy doody" in the filename
find * -name "*howdy doody*" -print0 | xargs -0 ...

xargs é o que você precisa usar para dividir a saída com terminação nula de find -print0 . No seu exemplo, o echo é estranho; não se incomode com isso.

# find files containing "howdy doody"
find * -print0 | xargs -0 grep -l "howdy doody"

# find files containing "howdy doody" and do further processing

# multiple xargs version
find * -print0 | xargs -0 grep -l "howdy doody" | xargs -i{} do-something "{}"

# "sh -c" version
find * -print0 | xargs -0 -i{} sh -c 'grep -l "howdy doody" "{}" && do-something "{}"'

# notes: 
#   "sh -c" allows us to run a complex command with a single xargs
#   "{}" handles spaces-in-filename
#   handles any &&, ||, | command linking

Você também pode executar seu comando diretamente do find with -exec . A diferença é que find -exec executa o comando uma vez por arquivo encontrado; xargs adiciona nomes de arquivos ao final do comando (até o limite do sistema), portanto, ele executa o comando menos vezes. Você pode simular isso com xargs -n1 para forçar xargs a executar apenas um comando por entrada.

# grep once per file
find * -exec grep -l "howdy doody" {} \; | ...
    
por 07.12.2009 / 21:40
3

Você pode fazer tudo em um comando, usando o argumento -exec para find :

find . -name "*howdy doody*" -exec echo I found file {} hooray \;

O ponto e vírgula escapado no final do comando a ser executado é exigido por find .

Ou, se você estiver procurando no conteúdo dos arquivos:

grep -R "howdy doody" *

Isso mostrará todas as correspondências de texto, adicione -l ao grep para obter apenas uma lista de arquivos

    
por 07.12.2009 / 23:23