Sim, existem várias maneiras de fazer isso com o comando find
. Vou listar alguns na ordem que acho importante para entender sua situação.
-
Seu script parece aceitar vários argumentos de nome de arquivo, portanto, a maneira mais eficiente e quase universal de realizar isso usando o comando
find
é:find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
Isso executa o seu script com tantos argumentos de nome de arquivo encontrados quanto possível. Seu script será chamado várias vezes, se necessário, para processar todos os nomes de arquivos. Observe o
+
no final da linha. -
Este é o método original e mais universal. Isso é menos eficiente para sua situação porque invoca
perl
uma vez para cada arquivo encontrado. Esse uso está disponível desde os primeiros dias do Unix . Observe o ponto e vírgula escapado (\;
) no final da linha (em oposição ao+
acima).find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
-
Antes de a sintaxe
-exec ... +
ser adicionada afind
, o comandoxargs
foi inventado para ajudar a aumentar a eficiência ao processar listas de nomes de arquivos ou outros argumentos. Isso funciona quase de forma idêntica ao exemplo-exec ... +
acima:find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
Se sua implementação for compatível, você deve usar a opção
-print0
defind
, junto com o argumento-0
paraxargs
. Isso faz com quefind
imprima caracteres nulos entre as sequências de argumentos e impede quexargs
divida os argumentos em nada, exceto no caractere nulo. Isso ajuda a impedir quexargs
divida os argumentos incorretamente, caso seus nomes de arquivos contenham espaços em branco ou outros caracteres especiais.Usar a sintaxe
-exec ... +
geralmente é uma ideia melhor porquefind
coloca os nomes de arquivos diretamente na lista de argumentos do seu script, eliminando um processo e evitando qualquer interpretação que possa ocorrer ao canalizar paraxargs
. No entanto,xargs
pode ter vantagens se você precisar de mais controle sobre o processo. Veja a páginaxargs
man. -
Você também pode verificar o comando
find2perl
, que recebe os mesmos argumentos defind
e imprime um programaperl
para fazer a mesma coisa. Você poderia então incorporar o códigoperl
gerado em seu script. No script gerado abaixo, você modificaria o próximo da última linha para chamar sua função em vez deprint
.$ find2perl foo -type f -name \*.txt # /* #[some preamble code removed for brevity] # Traverse desired filesystems File::Find::find({wanted => \&wanted}, 'foo'); exit; sub wanted { my ($dev,$ino,$mode,$nlink,$uid,$gid); (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _ && /^.*\.txt\z/s && print("$name\n"); }