Passando argumentos de um comando para o próximo

4

Estou tentando escrever um script para unificar dois comandos separados que eu executo à mão em um único script bash que eu posso, então, cron.

O primeiro comando é um simples achado em arquivos com um certo nome e tamanho

find /some/path -type f -name file.pl -size +10M

Isso produzirá vários arquivos correspondentes e seu caminho completo. Em seguida, copio esses caminhos manualmente em um loop for como argumentos para o próximo script.

for path in /some/path/1/file.pl /some/path/2/file.pl /some/path/3/file.pl ; do perl /my/script.pl $path ; done

Parece que deve ser fácil colocar isso em um único script de shell, mas é difícil.

    
por Morrison 14.08.2014 / 12:52

3 respostas

5

É para isso que serve o predicado -exec :

find /some/path -type f -name file.pl -size +10M -exec perl /my/script.pl {} \;

Se você quiser que o seu shell execute os comandos com base na saída de find , então isso terá que ser bash / zsh específico se você quiser ser confiável como em:

  • zsh :

    IFS=$'
    for f (./**/file.pl(.LM+10)) /my/script.pl $f
    
    ' for f ($(find /some/path -type f -name file.pl -size +10M -print0)) { /my/script.pl $f }

    embora em zsh , você pode simplesmente fazer:

    while IFS= read -rd '' -u3 file; do
      /my/script.pl "$file"
    done 3< <(find /some/path -type f -name file.pl -size +10M -print0)
    
  • bash / zsh

    for file in $(find...)
    

Seja o que for que você faça, em bash ou outros shells POSIX, evite:

IFS='
'; set -f; for file in $(find...)

Ou, pelo menos, reduza o problema fixando o separador de campo na nova linha e desabilitando a globbing:

find /some/path -type f -name file.pl -size +10M -exec perl /my/script.pl {} \;

(que ainda falhará nos caminhos de arquivo que contêm caracteres de nova linha).

    
por 14.08.2014 / 13:46
3

Se você estiver usando as ferramentas GNU, o seguinte também deve funcionar:

find /some/path -type f -name file.pl -size +10M -print0 | xargs -0 -n 1 -r perl /my/script.pl

Explicação:

  • A opção -print0 faz com que o GNU encontre para separar os nomes dos arquivos com -0 bytes. Como -n 1 bytes não pode fazer parte do nome do arquivo, isso separa exclusivamente os nomes dos arquivos.
  • A opção -r diz ao GNU xargs para ler a entrada padrão como a lista de nomes de arquivos %code% -separados.
  • A opção %code% impõe que não mais do que um nome de arquivo seja passado para o seu script (se o seu script puder manipular uma lista completa de arquivos como argumento, apenas omita isso).
  • Finalmente, %code% é outra extensão do GNU que impede que seu programa seja executado se nenhum nome de arquivo for fornecido.
por 14.08.2014 / 15:19
-3

Isso deve ser feito

for path in 'find /some/path -type f -name file.pl -size +10M'; do perl /my/script.pl $path ;done
    
por 14.08.2014 / 12:59