Suponha que eu tenha alguma saída de um comando (como ls -1
):
a
b
c
d
e
...
Eu quero aplicar um comando (digamos echo
) a cada um, por sua vez. Por exemplo
echo a
echo b
echo c
echo d
echo e
...
Qual é a maneira mais fácil de fazer isso no bash?
ls -1
pode ser um exemplo aqui, mas é importante lembrar que não é bom analisar a saída dels
. Veja: mywiki.wooledge.org/ParsingLsRespostas:
Provavelmente é mais fácil de usar
xargs
. No seu caso:O
-L
sinalizador garante que a entrada seja lida corretamente. Na página do manual dexargs
:fonte
ls
faz automaticamente-1
em um tubo.ls | xargs -L2 echo
els -1 | xargs -L2 echo
dê duas saídas diferentes. O primeiro sendo todos em uma linha.xargs
pode executar apenas arquivos executáveis, não funções de shell ou comandos internos do shell. Para o primeiro, a melhor solução é provavelmente a que apresentaread
um loop.-L1
é para isso.Você pode usar uma operação de pré-adição básica em cada linha:
Ou você pode canalizar a saída para sed para operações mais complexas:
fonte
sh: cho: not found a sh: cho: not found
parece que está aceitando oe
eco como um comando sed ou algo assim.while
loop.cmd1 | while read line; do cmd2 $line; done
. Ouwhile read line; do cmd2 $line; done < <(cmd1)
que não cria um subshell. Esta é a versão simplificada do seused
comando:sed 's/.*/echo &/'
"$line"
loop while, para evitar a divisão de palavras.read -r line
para evitarread
mexer com caracteres de escape. Por exemplo ,echo '"a \"nested\" quote"' | while read line; do echo "$line"; done
dá"a "nested" quote"
, que perdeu sua fuga. Seecho '"a \"nested\" quote"' | while read -r line; do echo "$line"; done
conseguirmos,"a \"nested\" quote"
como esperado. Veja wiki.bash-hackers.org/commands/builtin/readVocê pode usar um loop for :
Observe que, se o comando em questão aceitar vários argumentos, o uso de xargs é quase sempre mais eficiente, pois ele só precisa gerar o utilitário em questão uma vez em vez de várias vezes.
fonte
printf '%s\0' * | xargs -0 ...
- caso contrário, é muito inseguro com nomes de arquivos com espaços em branco, citações, etc.Você realmente pode usar o sed para fazer isso, desde que seja o GNU sed.
Como funciona:
fonte
cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
Se o cmd tiver uma saída grande:
fonte
cmd
houver espaços em sua saída, o primeiro falhará.xargs falha com barras invertidas, aspas. Precisa ser algo como
xargs -0 opção:
ls -1
finaliza os itens com caracteres de nova linha,tr
convertendo-os em caracteres nulos.Essa abordagem é cerca de 50 vezes mais lenta do que a iteração manualmente com
for ...
(consulte a resposta de Michael Aaron Safyan ) (3,55s vs. 0,066s). Mas, para outros comandos de entrada, como localizar, localizar, ler de um arquivo (tr \\n \\0 <file
) ou similar, você precisa trabalharxargs
assim.fonte
Melhor resultado para mim:
fonte
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 command
tratará dos casos em que a saída dels -1
é ambígua; use-printf '%P\0'
ao invés de-print0
se você não quer uma liderança./
em cada um.eu gosto de usar o gawk para executar vários comandos em uma lista, por exemplo
no entanto, a fuga dos personagens escapáveis pode ficar um pouco peluda.
fonte