xargs è la soluzione più flessibile per suddividere l'output in argomenti di comando.
È anche molto leggibile e facile da usare grazie alla sua semplice parametrizzazione.
Il formato è xargs -n $NUMLINES mycommand .
Ad esempio, a echo ogni singola riga in un file /tmp/tmp.txt faresti:
cat /tmp/tmp.txt | xargs -n 1 echo
O a diff ogni coppia successiva di file elencati come righe in un file con il nome sopra che faresti:
cat /tmp/tmp.txt | xargs -n 2 diff
Il -n 2 istruisce xargs consumare e passare come argomenti separati due righe alla volta di ciò che ci hai inviato.
Puoi personalizzare xargs per dividere sui delimitatori oltre a ritorno a capo/nuova riga.
Usa man xargs e google per saperne di più sulla potenza di questa versatile utility.
Il modo migliore per farlo è reindirizzare il file nel ciclo:
# Basic idea. Keep reading for improvements.
FILE=test
while read CMD; do
echo "$CMD"
done < "$FILE"
Un reindirizzamento con < "$FILE" ha alcuni vantaggi rispetto a cat "$FILE" | while ... . Evita un uso inutile di cat, salvando un processo figlio non necessario. Evita anche una trappola comune in cui il ciclo viene eseguito in una subshell. In Bash, comandi in un | la pipeline viene eseguita in subshell, il che significa che le assegnazioni delle variabili vengono perse al termine del ciclo. Reindirizzamento con < non ha quel problema, quindi potresti usare $CMD dopo il ciclo o modificare altre variabili all'interno del ciclo. Inoltre, ancora una volta, evita processi figlio non necessari.
Ci sono alcuni miglioramenti aggiuntivi che potrebbero essere apportati:
- Aggiungi
IFS=in modo chereadnon taglierà gli spazi bianchi iniziali e finali da ogni riga. - Aggiungi
-rareadper evitare che le barre rovesciate vengano interpretate come sequenze di escape. CMDminuscolo eFILE. La convenzione di Bash è che solo le variabili ambientali e interne della shell sono maiuscole.- Usa
printfal posto diechoche è più sicuro se$cmdè una stringa come-n, cheechointerpreterebbe come una bandiera.
file=test
while IFS= read -r cmd; do
printf '%s\n' "$cmd"
done < "$file"
Quello che hai è convogliare il testo "cat test" nel ciclo.
Vuoi solo:
cat test | \
while read CMD; do
echo $CMD
done