Você pode fazer o seguinte usando algumas implementações de find
e xargs
desta forma.
$ find . -type f -print0 | xargs -r0 ./myscript
ou, normalmente, apenas find
:
$ find . -type f -exec ./myscript {} +
Exemplo
Digamos que eu tenha o seguinte diretório de amostra.
$ tree
.
|-- dir1
| '-- a\ file1.txt
|-- dir2
| '-- a\ file2.txt
|-- dir3
| '-- a\ file3.txt
'-- myscript
3 directories, 4 files
Agora digamos que eu tenha isso para ./myscript
.
#!/bin/bash
for i in "$@"; do
echo "file: $i"
done
Agora, quando eu executo o seguinte comando.
$ find . -type f -print0 | xargs -r0 ./myscript
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript
Ou quando eu uso a segunda forma assim:
$ find . -type f -exec ./myscript {} +
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript
Detalhes
encontre + xargs
Os 2 métodos acima, apesar de parecerem diferentes, são essencialmente os mesmos. A primeira é pegar a saída de find, dividindo-a usando NULLs (
) através da opção -print0
xargs -0
para localizar. O find
é especificamente projetado para receber entradas divididas usando NULLs. Essa sintaxe não padrão foi introduzida pelo GNU xargs
e -r
, mas também é encontrada hoje em dia em alguns outros como os BSDs mais recentes. A opção myscript
é necessária para evitar chamar find
se find
não encontrar nada com o GNU ./myscript
, mas não com os BSDs.
OBSERVAÇÃO: Essa abordagem toda depende do fato de que você nunca passará uma string que é excessivamente longa. Se for, então uma segunda invocação de find
será iniciada com o restante dos resultados subseqüentes encontrados.
encontre com +
Essa é a maneira padrão (embora tenha sido adicionada recentemente (2005) à implementação GNU de xargs
). A capacidade de fazer o que estamos fazendo com find
é literalmente incorporada em find
. Portanto, -exec
encontrará uma lista de arquivos e passará essa lista com tantos argumentos quantos couberem ao comando especificado após {}
(observe que +
pode ser apenas anterior a xargs
neste caso), executando os comandos várias vezes, se necessário.
Por que não citar?
No primeiro exemplo, estamos pegando um atalho, evitando completamente os problemas com as citações, usando NULLs para separar os argumentos. Quando find
recebe essa lista, ela é instruída a dividir os NULLs efetivamente protegendo nossos átomos de comando individuais.
No segundo exemplo, estamos mantendo os resultados internos em xargs
e, portanto, sabemos qual é o átomo de cada arquivo e garantiremos que eles sejam manipulados adequadamente, evitando, assim, o negócio de citá-los.
Tamanho máximo da linha de comando?
Essa pergunta surge de tempos em tempos, então, como bônus, estou adicionando a essa resposta, principalmente para poder encontrá-la no futuro. Você pode usar %code% para ver o limite do ambiente assim:
$ xargs --show-limits
Your environment variables take up 4791 bytes
POSIX upper limit on argument length (this system): 2090313
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2085522
Size of command buffer we are actually using: 131072