Melhor maneira de executar um comando em cada arquivo em uma árvore de diretórios

13

Parece haver várias maneiras de fazer isso, incluindo loops no shell script, find e xargs. Qual destes é o melhor e qual é o mais portátil?

Brian Lyttle
fonte

Respostas:

13
find . -exec <command> {} \;

para o diretório atual como a raiz da árvore ou em geral:

find <directory> -exec <command> {} \;
txwikinger
fonte
4
Em alguns sistemas, o find não possui a opção -exec. Você pode usar o find. | xargs <Command>
Hemant
4
Na verdade, e se você precisa para filtrar por algo, tente -name "*.c"ou, por exemplo -type dpara os diretórios ...
O Find pode fazer coisas surpreendentemente complexas - você pode verificar a página de manual - unixhelp.ed.ac.uk/CGI/man-cgi?find - para obter a lista completa de opções.
Lucas Jones
Você também pode querer observar nomes de arquivos com espaços, o que pode quebrar a abordagem -exec e xargs. Veja tinyurl.com/ygvgmw5
Shawn Chin
Se possível, use o find ... | xargs ...idioma, ele processa arquivos em lotes, e isso geralmente será mais rápido (menos processos iniciados).
vonbrand
5

Use a -print0opção para localizar e a -0opção xargsse você tiver nomes de arquivos ou diretórios com espaços:

find {dir} -print0 | xargs -0r {command}

A -print0opção de localizar imprime os nomes de arquivos como uma NULlista separada por espaços em branco e não por espaço em branco, enquanto a -0opção para xargsinstruí-lo a interromper sua entrada em NULvez de espaço em branco. Como NULé um dos caracteres que não é permitido nos nomes de arquivos Unix, não há como confundir parte de um nome de arquivo.

A -ropção existe para que xargsnão ocorra um erro se não houver entrada.

dhd
fonte
3

Se a portabilidade for um problema, eu ficaria longe de maneiras específicas de fazer isso (existem muitas pessoas usando muitas conchas diferentes, mas, em geral, o find e o xargs são realmente ferramentas básicas que ninguém ousaria mudar de maneira radical) .

O uso de argumentos básicos de find e xargs deve fornecer uma solução mais portátil.

nc3b
fonte
2

Se agrupar argumentos for aceitável, localize | O xargs provavelmente oferecerá melhor desempenho, pois executará o comando muito menos vezes do que o find -exec. Se você deseja executar o comando todas as vezes para cada arquivo ou executar no subdiretório do arquivo, provavelmente deve usar find -exec ou -execdir.

Como regra, é preferível ficar longe de loops específicos de shell; find & xargs são suficientes para a maioria dos cenários.

Eugen Anghel
fonte
1

Verifique se a versão do comando que você está usando ainda não possui um sinalizador para operação recursiva. :)


fonte
0
find [args] -print | xargs {command}

Funciona melhor para mim.

Josh K
fonte
2
-1 Não funcionará para nomes de arquivos que contenham espaços. Melhor usar find -print0 | xargs -0.
Starblue