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 quereadne supprimera pas les espaces de début et de fin de chaque ligne. - Ajouter
-ràreadpour éviter que les barres obliques inverses soient interprétées comme des séquences d'échappement. - En minuscules
CMDetFILE. La convention Bash est que seules les variables environnementales et internes du shell sont en majuscules. - Utilisez
printfà la place deechoce qui est plus sûr si$cmdest une chaîne comme-n, quiechoserait 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