Execute as linhas de saída do comando como outro comando no linux

0

Estou executando este comando:

find ./ -type f -printf "wc -l \"%p\"\n"

que dá esta saída:

wc -l "ANLS 457567.pl"
wc -l "ANLS 457567.pl"

Agora quero executar essa linha inteira como outro comando.

Como posso conseguir isso?

Eu sei que posso usar xargs para passar sua saída como argumentos para outro comando, mas por curiosidade eu quero saber se isso ( Executar linhas de saída do comando como outro comando ) é possível.

    
por AbhiNickz 19.10.2016 / 10:10

3 respostas

1

Apenas passe para STDIN da shell:

find ./  -type f -printf "wc -l \"%p\"\n" | sh 

ou se o shell suportar a substituição do processo, <() :

sh <(find ./  -type f -printf "wc -l \"%p\"\n")

Com apenas find :

find ./  -type f -exec wc -l {} +
    
por 19.10.2016 / 10:12
3

Embora você possa canalizar comandos como esse para um shell, ele pode tornar um tanto muito problemático, já que quaisquer globs e variáveis e outros serão expandidos.

Nomes de arquivos contendo, por exemplo asteriscos ( * , glob) ou cifrões ( $ , variável e expansão de comando) causarão problemas. Você precisa se certificar de citar tudo corretamente e, no caso geral, seus nomes de arquivo podem conter citações, por isso não é tão fácil.

Mas, no caso de find , ele pode executar comandos externos:

find ./  -type f -exec wc -l {} \;

o {} é substituído pelo nome do arquivo atual e o ponto e vírgula (cotado) no final é obrigatório.

Pelo menos algumas versões do find suportam um formato alternativo que fornece vários nomes de arquivos para comandar de uma só vez, salvando um monte de execuções:

find ./  -type f -exec wc -l {} \+
    
por 19.10.2016 / 10:19
0

Veja o comentário de @ilkkachu para a solução prática para este caso. Mas caso contrário, o shell expande as variáveis antes de executar cada linha, então

find ./  -type f -printf "wc -l %p\n" | while read line; do
    $line
done

funcionará muito bem (a menos que caracteres especiais sejam encontrados em espaços semelhantes a nomes de arquivos).

Observe como $line não tem aspas e não citamos %p . Isso porque nós queremos que o shell divida a linha em palavras antes da execução - tratando as palavras de $line como o comando e seus argumentos, como se você mesmo as tivesse escrito. É por isso que os espaços não funcionam.

Isso é evitado usando o shell eval embutido, que realmente funciona exatamente como você digitou o comando no shell - incluindo as aspas (que estão de volta agora):

find ./  -type f -printf "wc -l \"%p\"\n" | while read line; do
    eval $line
done

Este último deve funcionar em todos os casos - mas ainda não é uma boa prática. eval deve ser o último recurso. Estou incluindo essas opções apenas para que você saiba que elas funcionam, mas geralmente há maneiras melhores, como a opção -exec de find .

    
por 19.10.2016 / 10:26