Como esse código pode ser alterado para não dar erro, ou seja, não executar o código depois xargs
se stdout estiver vazio.
Terminal:
$ cat << EOF > dummy.sh
#! /usr/bin/env bash
[[ -f "\$1" ]] && echo "file=\$1" || { echo "error"; exit 1; }
shift
(( \$# == 0 )) || "\$0" "\$@"
EOF
$ chmod +x dummy.sh
$ mkdir trash.later && touch trash.later/foo
$ find trash.later -type f | xargs -n 1 ./dummy.sh
file=trash.later/foo
$ find trash.later -type f | grep 'bar' | xargs -n 1 ./dummy.sh
error
Não use
xargs
na saída defind
.xargs
por padrão, espera que os argumentos na entrada sejam delimitados em um formato que nenhum comando produza, certamente nãofind
. A saída defind -print
também não é pós-processável de forma confiável.A única maneira de usar
find
dexargs
forma confiável é usando as extensões-print0
e-0
não padrão (inicialmente do GNUfind
/xargs
, mas hoje em dia encontradas em muitas outras implementações).O GNU
xargs
também possui uma extensão-r
/--no-run-if-empty
para não executar o comando se a entrada estiver vazia (algumasxargs
implementações como a do NetBSD fazem isso por padrão).Então aqui, com GNU
find
//xargs
ougrep
compatível, você poderia fazer:Mas isso não tem vantagem sobre o padrão:
(onde
-path '*bar*'
procura embar
qualquer lugar no caminho do arquivo como vocêgrep bar
tentou fazer. Substitua por-name '*bar*'
procurarbar
apenas no nome do arquivo (o último componente de seu caminho)).Mais leitura sobre isso em Por que o loop sobre a saída de find é uma prática ruim?
Como uma resposta mais geral à sua pergunta, para
xargs
implementações que não suportam-r
/--no-run-if-empty
, a solução é usar umsh
wrapper.Ao invés de:
Faz:
Isso ainda é executado
sh
se não houver entrada, mas como a lista de argumentos está vazia, não haverá passagem no loop, portantocmd
, não será executado.Veja também o
ifne
comando a partir domoreutils
qual só executa o comando se a entrada não estiver vaziaNo entanto, observe que se a entrada não estiver vazia, mas contiver apenas linhas em branco,
ifne
será executado ,xargs
masxargs
ainda considerará que sua entrada não tem argumento e ainda será executadocmd
uma vez sem argumento (exceto no NetBSD).Para completar
também não será executado
cmd
se a entrada estiver vazia/em branco. Nesse caso, a divisão da entrada em argumentos é diferente: os espaços em branco iniciais são removidos, as aspas ainda são processadas (dexargs
uma maneira muito própria), mas, caso contrário, os argumentos são linhas inteiras em vez de palavras separadas em branco.