find: -exec vs xargs (aka Por que “find | xargs basename” quebra?)

10

Eu estava tentando encontrar todos os arquivos de um determinado tipo espalhados em subdiretórios, e para os meus propósitos eu só precisava do nome do arquivo. Eu tentei retirar o componente caminho via basename , mas não funcionou com xargs :

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand './pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try 'basename --help' for more information.

Eu obtenho a mesma coisa (exatamente o mesmo erro) com uma dessas variações:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

Isso, por outro lado, funciona como esperado:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

Isso acontece em Cygwin e Debian 5.0.3 atualizados. Meu diagnóstico é que o xargs está, por alguma razão, passando duas linhas de entrada para o nome base, mas por quê? O que está acontecendo aqui?

    
por quack quixote 08.10.2009 / 18:01

4 respostas

22

Porque basename quer apenas um parâmetro ... não muito. E xargs cria muitos parâmetros.

Para resolver seu problema real (liste apenas os nomes dos arquivos):

 find . -name '*.deb' -printf "%f\n"

Que imprime apenas o 'basename' (man find):

 %f     File's name with any leading directories
        removed (only the last element).
    
por 08.10.2009 / 18:06
17

Tente isto:

find . -name '*.deb' | xargs -n1 basename
    
por 08.10.2009 / 18:05
4

basename aceita apenas um único argumento. Usar -exec funciona corretamente porque cada {} é substituído pelo nome do arquivo atual que está sendo processado e o comando é executado uma vez por arquivo correspondente , em vez de tentar enviar todos os argumentos para basename em um vai.

    
por 08.10.2009 / 18:05
2

xargs pode ser forçado a passar apenas um argumento também ...

find . -name '*.deb' -print | xargs -n1 basename

Isso funciona, mas a resposta aceita é usar find de maneira mais apropriada. Eu encontrei esta pergunta procurando xargs basename problemas como eu estou usando outro comando para obter uma lista de locais de arquivos. O sinal -n1 para xargs foi a resposta final para mim.

    
por 11.07.2014 / 01:18