find: não faça nada, se nenhum arquivo for especificado

find: não faça nada, se nenhum arquivo for especificado

Quero chamar use findem alguns nomes de arquivos.

find $(do_something to find filenames) -print0 | xargs -r0 ls -ld

Isso é interrompido se $(do_something to find filenames)não retornar nada: o comando find começa a fazer uma pesquisa recursiva.

Existe uma maneira de dizer ao find para não fazer nada se não obtiver nenhum nome de arquivo/nome de diretório explícito como argumento?

Responder1

Com zsh, eu faria:

files=($(do_something to find filenames))
(($#files)) && find $files ...

Com tcsh:

set files=(`do_something to find filenames`)
if ($#files) find $files:q ...

Com bash, mkshou ksh93,

set -f; files=($(do_something to find filenames))
((${#files[@]})) && find "${files[@]}" ...

POSIXamente:

set -f; set -- $(do_something to find filenames)
[ "$#" -gt 0 ] && find "$@" ...

(no bash e em outros shells POSIX, $(...)divide (em $IFS: espaço, tabulação e nova linha por padrão), mas também executa globbing nas palavras resultantes que não espero que você queira aqui, portanto, o set -f. Outros shells ((t)csh , zsh, fish, rc, es...) não tem esse problema).

Responder2

Que tal fazer isso:

paths=$(do_something to find filenames)
if [ "$paths" ]; then
    find "$paths" ...
fi

Isso funciona independente da findimplementação.

Observe que find "$paths"ter mais de um nome de caminho causa problemas. Se os nomes dos caminhos não contiverem espaços, você poderá usar: find $paths, caso contrário, uma alternativa funcional é esta função:

dofind() {
    set -f
    set -- $(do_something to find filenames)
    if [ $# -gt 0 ]; then
        find "$@" ...
    fi
    set +f
}

Ele desativa o globbing de arquivos e, em seguida, usa set --para definir o vetor arg dos shells. Isso funciona com qualquer shell POSIX.

Responder3

Você pode fornecer findum diretório extra e inexistente para começar:

find " " $(do_something to find filenames) -print0 | xargs -r0 ls -ld

Para deixar isso organizado, descarte finda saída de erro de:

find " " $(do_something to find filenames) -print0 2>/dev/null | xargs -r0 ls -ld

(mas você não notará se ocorrer outro erro...).

Quando do_something to find filenamesgerar nomes de arquivos, findreclamará, " "mas ainda processará o resto da linha de comando. Quando nenhum nome de arquivo for gerado, findele reclamará novamente, " "mas não adicionará seu arquivo ..

Responder4

Em zsh(e na maioria dos shells não derivados de Bourne), quando um (outodosdependendo da casca)globonão se expande, o comando é abortado.

$(do_something to find filenames)não é um glob, mas você pode torná-lo um anexando um qualificador glob em zsh:

 find $(do_something to find filenames)(#q) -print0...

Acima, isso (#q)(um qualificador glob vazio, então não faz nada de outra forma) é anexado à última palavra resultante da divisão da saída de do_something to find filenames, então o comando será abortado se esse comando não produzir saída (ou em branco), mas também se isso a última palavra (e apenas essa última palavra) não resolve um caminho existente. Você pode aplicá-lo a todas as palavras resultantes dessa divisão (para que o comando seja abortado se alguma dessas palavras não resolver para um arquivo existente) com:

 find ${^$(do_something to find filenames)}(#q) -print0...

informação relacionada