Supponiamo di avere un output da un comando (come ls -1):
a
b
c
d
e
...
Voglio applicare un comando (diciamo echo) a ciascuno, a sua volta. Per esempio
echo a
echo b
echo c
echo d
echo e
...
Qual è il modo più semplice per farlo in bash?
Supponiamo di avere un output da un comando (come ls -1):
a
b
c
d
e
...
Voglio applicare un comando (diciamo echo) a ciascuno, a sua volta. Per esempio
echo a
echo b
echo c
echo d
echo e
...
Qual è il modo più semplice per farlo in bash?
Risposte:
Probabilmente è più facile da usare xargs. Nel tuo caso:
ls -1 | xargs -L1 echo
Il -Lflag assicura che l'ingresso sia letto correttamente. Dalla pagina man di xargs:
-L number
Call utility for every number non-empty lines read.
A line ending with a space continues to the next non-empty line. [...]
lsfa automaticamente -1in un tubo.
ls | xargs -L2 echoe dai ls -1 | xargs -L2 echodue uscite diverse. Il primo è tutto su una linea.
xargspuò eseguire solo file eseguibili non funzioni di shell o comandi incorporati della shell. Per il primo la soluzione migliore è probabilmente quella con readin un ciclo.
-L1serve.
È possibile utilizzare un'operazione anteposta di base su ciascuna riga:
ls -1 | while read line ; do echo $line ; done
Oppure puoi reindirizzare l'output a sed per operazioni più complesse:
ls -1 | sed 's/^\(.*\)$/echo \1/'
sh: cho: not found a sh: cho: not foundsembra che l' eeco in sia un comando sed o qualcosa del genere.
whileciclo. cmd1 | while read line; do cmd2 $line; done. O while read line; do cmd2 $line; done < <(cmd1)che non crea una subshell. Questa è la versione semplificata del tuo sedcomando:sed 's/.*/echo &/'
"$line"ciclo while, per evitare la divisione delle parole.
read -r lineper evitare di readscherzare con i caratteri di escape. Ad esempio echo '"a \"nested\" quote"' | while read line; do echo "$line"; donedà "a "nested" quote", che ha perso la sua fuga. Se lo facciamo echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; doneotteniamo "a \"nested\" quote"come previsto. Vedi wiki.bash-hackers.org/commands/builtin/read
Puoi usare un ciclo for :
per file in *; fare echo "$ file" fatto
Si noti che se il comando in questione accetta più argomenti, l'utilizzo di xargs è quasi sempre più efficiente in quanto deve generare l'utilità in questione solo una volta anziché più volte.
printf '%s\0' * | xargs -0 ...- altrimenti, non è abbastanza sicuro con nomi di file con spazi bianchi, virgolette, ecc.
In realtà puoi usare sed per farlo, a condizione che sia GNU sed.
... | sed 's/match/command \0/e'
Come funziona:
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'
for s in `cmd`; do echo $s; done
Se cmd ha un output di grandi dimensioni:
cmd | xargs -L1 echo
cmdha spazi nel suo output, il primo fallirà.
xargs fallisce con barre rovesciate, virgolette. Deve essere qualcosa di simile
ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."
xargs -0 opzione:
-0, --null Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
ls -1termina gli elementi con caratteri di nuova riga, quindi trli traduce in caratteri null.
Questo approccio è circa 50 volte più lento dell'iterazione manuale con for ...(vedi la risposta di Michael Aaron Safyan ) (3.55s contro 0.066s). Ma per altri comandi di input come individuare, trovare, leggere da un file ( tr \\n \\0 <file) o simili, devi lavorare in xargsquesto modo.
Risultato migliore per me:
ls -1 | xargs -L1 -d "\n" CMD
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 commandgestirà i casi in cui l'output di ls -1è ambiguo; usa -printf '%P\0'piuttosto che -print0se non vuoi un vantaggio ./su ciascuno.
ls -1può essere un esempio qui, ma è importante ricordare che non è utile analizzare l'output dils. Vedi: mywiki.wooledge.org/ParsingLs