Eu entendo que -exec
pode ter uma +
opção para imitar o comportamento de xargs
. Existe alguma situação em que você “preferiria uma forma em vez da outra?
Pessoalmente, tendo a preferir a primeira forma, mesmo que apenas para evitar o uso de um tubo. Acho que certamente os desenvolvedores de find
deve” ter feito as otimizações apropriadas. Estou correto?
Resposta
Você pode querer encadear chamadas para encontrar (uma vez, quando você aprendeu, que é possível , que pode ser hoje). Isso, é claro, só é possível enquanto você permanecer em busca. Depois de enviar para xargs, ele “está fora do escopo.
Pequeno exemplo, dois arquivos a.lst e b.lst:
cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh
Nenhum truque aqui – simplesmente o fato de que ambos contêm “fuddel”, mas apenas um contém “fiddel”.
Suponha que não soubéssemos disso. Procuramos um arquivo que corresponda a 2 condições:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls 192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Bem, talvez você conheça a sintaxe do grep ou de outro programa para passar ambas as strings como condição, mas que ” Esse não é o ponto. Todo programa que pode retornar verdadeiro ou falso, dado um arquivo como argumento, pode ser usado aqui – grep foi apenas um exemplo popular.
E observe, você pode seguir find -exec com outros comandos de localização, como -ls ou -delete ou algo semelhante. Observe que a exclusão não apenas rm (remove arquivos), mas também rmdir (remove diretórios) também.
Tal cadeia é lida como uma combinação AND de comandos, desde que não seja especificado de outra forma (ou seja, com uma opção -or
(e parênteses (que precisam ser mascarados))).
Então, você não está deixando a cadeia de localização, o que é uma coisa útil. Não vejo nenhuma vantagem em usar -xargs, já que você deve ter cuidado ao passar os arquivos, o que o find não precisa fazer – ele trata automaticamente a passagem de cada arquivo como um único argumento para você.
Se você acredita que precisa de algum mascaramento para encontrar {} colchetes , fique à vontade para visitar minha pergunta que pede evidências. Minha afirmação é: Você não.
Comentários
Resposta
O encaminhamento seguro de nomes de arquivos para xargs
requer que seu find
suporte o -print0
opção e seu xargs
tem a opção correspondente para lê-lo (--null
ou -0
). Caso contrário, nomes de arquivos com unprintab Os caracteres le ou barras invertidas ou aspas ou espaços em branco no nome podem causar um comportamento inesperado. Por outro lado, find -exec {} +
está na POSIX find
especificação , por isso é portátil e é quase tão seguro quanto find -print0 | xargs -0
e definitivamente mais seguro do que find | xargs
. Eu recomendo nunca fazer find | xargs
sem -print0
.
Comentários
- Uma exceção notável à portabilidade de
find … -exec … {} +
é o OpenBSD, que só adquiriu esse recurso com a versão 5.1 lançada em 2012. Todos os BSDs tiveram-print0
por vários anos, até mesmo o OpenBSD (embora tenha resistido a esse recurso por um tempo também). Solaris, por outro lado, mantém os recursos POSIX, então você obtém-exec +
e nenhum-print0
. -
-print0
é chato e você pode argumentarxargs --delimiter "\n"
isn ‘ t equivalente, eu ‘ nunca usei o primeiro depois de descobrir o último . - Não ‘ não vejo como
-0
é mais chato do que--delimiter "\n"
. - Além de
-0
, GNUxargs
precisa de-r
para evitar a execução do comando se ‘ não houver entrada. - Outro problema de
| xargs -r0 cmd
é quecmd
‘ s stdin é afetado (dependendo daxargs
implementação, ele ‘ s/dev/null
ou o pipe.
Resposta
Se você usar a forma -exec ... ;
(lembrando para escapar do ponto-e-vírgula), você está executando o comando uma vez por nome de arquivo. Se usar -print0 | xargs -0
, você executará vários comandos por nome de arquivo. Você definitivamente deve usar o -exec +
formulário, que coloca vários arquivos em uma única linha de comando e é muito mais rápido quando um grande número de arquivos está envolvido.
Uma grande vantagem de usar xargs
é a capacidade de executar vários comandos em paralelo usando xargs -P
. Em sistemas com vários núcleos, isso pode proporcionar uma grande economia de tempo.
Comentários
- Você quis dizer
-P
em vez de-p
. Lembre-se de quexargs -P
não está no padrão POSIX, enquantofind -exec {} +
está, o que é importante se você deseja portabilidade. - @Alexios Você não ‘ não precisa escapar do sinal de mais, porque ele não tem um significado especial para o shell:
find /tmp/ -exec ls "{}" +
funciona muito bem. - Corrente, é claro. Eu ‘ tenho escapado de tudo depois do
-exec
por tanto tempo (eu ‘ ma masoquista , Eu não ‘ nem mesmo uso aspas para escapar{}
, sempre digito\{\}
; não ‘ não pergunte), tudo parece que deve ser escapado agora. - @Alexios: Se você encontrar um exemplo (exceto por ser um masoquista) onde o mascarar as chaves é útil, forneça-o como uma resposta à minha pergunta aqui – afaik esta dica está desatualizada e é apenas um relíquia na página de manual. Eu ‘ nunca vi um exemplo em que
find /tmp/ -exec ls {} +
‘ não funcionasse. - Para mim, esta é a memória muscular formada na época do SunOS 4. Como ‘ faço isso há anos, não percebi quando
bash
começou a aceitar as chaves literalmente. Eu ‘ tenho certeza de que pelo menos uma das conchas antigas que ‘ usei com encaixes sibilantes se as chaves não tivessem ‘ t escapou.
Resposta
Com relação ao desempenho, pensei que -exec … +
seria simplesmente melhor porque é “uma ferramenta única fazendo todo o trabalho, mas uma parte da documentação do GNU findutil diz que -exec … +
pode ser menos eficiente em alguns casos:
[encontre com
-exec … +
] pode ser menos eficiente do que alguns usos dexargs
; por exemplo,xargs
permite que novas linhas de comando sejam construídas enquanto o comando anterior ainda está em execução e permite que você especifique um número de comandos a serem executados em paralelo. No entanto, a construçãofind ... -exec ... +
tem a vantagem de ampla portabilidade. GNU findutils não suportava ‘-exec ... +
’ até a versão 4.2.12 [janeiro de 2005] ; uma das razões para isso é que ele já tinha a ação ‘-print0
’ em qualquer caso.
Não tinha certeza do que isso significava, então perguntei no bate-papo onde derobert explicou isso como:
find
provavelmente poderia continuar a procurar o próximo lote de arquivos enquanto o-exec … +
está em execução, mas não.
find … | xargs …
está, porque então a localização é um processo diferente e mantém executando até que o buffer do pipe se encha
(Formatando por mim.)
Então é isso. Mas se o desempenho realmente importa, você teria que fazer um benchmarking realista ou melhor, até mesmo se perguntar se você gostaria de usar o shell para esses casos.
Aqui neste site eu acho que é melhor aconselhar as pessoas a use a forma -exec … +
sempre que possível porque é mais simples e pelos motivos mencionados nas outras respostas aqui (por exemplo, lidar com nomes de arquivos estranhos sem ter que pensar muito).
find
. Muito obrigado!-exec
maneira de fazerxargs -P4
para que três dos quatro núcleos não ‘ fiquem inativos?