xargs
est la solution la plus flexible pour diviser la sortie en arguments de commande.
Il est également très lisible par l'homme et facile à utiliser grâce à son paramétrage simple.
Le format est xargs -n $NUMLINES mycommand
.
Par exemple, à echo
chaque ligne individuelle dans un fichier /tmp/tmp.txt
vous feriez :
cat /tmp/tmp.txt | xargs -n 1 echo
Ou à diff
chaque paire successive de fichiers répertoriés sous forme de lignes dans un fichier du nom ci-dessus, vous feriez :
cat /tmp/tmp.txt | xargs -n 2 diff
Le -n 2
ordonne xargs
pour consommer et transmettre en tant qu'arguments séparés deux lignes de ce que vous avez ajouté à la fois.
Vous pouvez personnaliser xargs
pour diviser sur les délimiteurs en plus du retour chariot/nouvelle ligne.
Utilisez man xargs
et google pour en savoir plus sur la puissance de cet utilitaire polyvalent.
La meilleure façon de procéder est de rediriger le fichier dans la boucle :
# Basic idea. Keep reading for improvements.
FILE=test
while read CMD; do
echo "$CMD"
done < "$FILE"
Une redirection avec < "$FILE"
présente quelques avantages par rapport à cat "$FILE" | while ...
. Cela évite une utilisation inutile de cat, épargnant ainsi un processus fils inutile. Cela évite également un écueil courant où la boucle s'exécute dans un sous-shell. Dans Bash, les commandes dans un |
pipeline exécuté dans des sous-shells, ce qui signifie que les affectations de variables sont perdues après la fin de la boucle. Redirection avec <
n'a pas ce problème, vous pouvez donc utiliser $CMD
après la boucle ou modifier d'autres variables à l'intérieur de la boucle. Cela évite également, encore une fois, les processus enfants inutiles.
Certaines améliorations supplémentaires pourraient être apportées :
- Ajouter
IFS=
de sorte queread
ne supprimera pas les espaces de début et de fin de chaque ligne. - Ajouter
-r
àread
pour éviter que les barres obliques inverses soient interprétées comme des séquences d'échappement. - En minuscules
CMD
etFILE
. La convention Bash est que seules les variables environnementales et internes du shell sont en majuscules. - Utilisez
printf
à la place deecho
ce qui est plus sûr si$cmd
est une chaîne comme-n
, quiecho
serait interprété comme un drapeau.
file=test
while IFS= read -r cmd; do
printf '%s\n' "$cmd"
done < "$file"
Ce que vous avez, c'est le texte "cat test"
dans la boucle.
Vous voulez juste :
cat test | \
while read CMD; do
echo $CMD
done