Como posso manipular espaços em nomes de arquivos ao usar xargs em resultados de busca?

26

Uma das minhas práticas comuns é executar greps em todos os arquivos de um determinado tipo, por exemplo, encontrar todos os arquivos HTML que tenham a palavra "rumpus" neles. Para fazer isso, eu uso

find /path/to -name "*.html" | xargs grep -l "rumpus"

Ocasionalmente, find retornará um arquivo com um espaço em seu nome, como my new file.html . Quando xargs passou isso para grep , no entanto, recebo esses erros:

grep: /path/to/bad/file/my: No such file or directory
grep: new: No such file or directory
grep: file.html: No such file or directory

Eu posso ver o que está acontecendo aqui: o pipe ou o xargs está tratando os espaços como delimitadores entre os arquivos. Para a vida de mim, no entanto, não consigo descobrir como evitar esse comportamento. Pode ser feito com find + xargs ? Ou eu tenho que usar um comando totalmente diferente?

    
por abeger 10.05.2011 / 23:08

3 respostas

27

Use

find ... -print0 | xargs -0 ...

por exemplo,

find /path/to -name "*.html"  -print0 | xargs -0  grep -l "rumpus"

da página man do encontro

-print0
          True; print the full file name on the standard  output,  followed
          by  a  null  character  (instead  of  the  newline character that
          ‘-print’ uses).  This allows file names that contain newlines  or
          other  types  of  white space to be correctly interpreted by pro-
          grams that process the find output.  This option  corresponds  to
          the ‘-0’ option of xargs.
    
por 10.05.2011 / 23:15
14

Você não precisa usar xargs , porque encontrar pode executar os próprios comandos. Ao fazer isso, você não precisa se preocupar com os caracteres de interpretação do shell no nome.

find /path/to -name "*.html" -exec grep -l "rumpus" '{}' +

da página man do encontro

-exec command {} +
This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of '{}' is allowed within the command. The command is executed in the starting directory.

    
por 10.05.2011 / 23:29
8

Se as versões find e xarg no seu sistema não suportarem -print0 e -0 switches (por exemplo, AIX find e xargs), você poderá usar isto:

find /your/path -name "*.html" | sed 's/ /\ /g' | xargs grep -l "rumpus"

Aqui sed irá cuidar de escapar dos espaços para xargs.

    
por 27.03.2015 / 15:22