Comment passer chaque ligne d'un file text en argument à une command?

Je cherche à écrire un script qui prend un nom de file .txt comme argument, lit le file ligne par ligne et passe chaque ligne à une command. Par exemple, il exécute la command --option "LINE 1" , puis command --option "LINE 2" , etc. La sortie de la command est écrite dans un autre file. Comment je fais ça? Je ne sais pas où commencer.

Utiliser while read boucle de while read :

 : > another_file ## Truncate file. while read -r LINE; do command --option "$LINE" >> another_file done < file 

Une autre est de redirect la sortie par bloc:

 while read -r LINE; do command --option "$LINE" done < file > another_file 

Le dernier est d'ouvrir le file:

 exec 4> another_file while read -r LINE; do command --option "$LINE" >&4 echo xyz ## Another optional command that sends output to stdout. done < file 

Si l'une des commands lit une input, ce serait une bonne idée d'utiliser un autre fd pour l'input afin que les commands ne le mangent pas (en supposant que ksh , zsh ou bash pour -u 3 ).

 while read -ru 3 LINE; do ... done 3< file 

Enfin pour accepter les arguments, vous pouvez faire:

 #!/bin/bash FILE=$1 ANOTHER_FILE=$2 exec 4> "$ANOTHER_FILE" while read -ru 3 LINE; do command --option "$LINE" >&4 done 3< "$FILE" 

Lequel pourrait fonctionner comme:

 bash script.sh file another_file 

Idée supplémentaire. Avec bash , utilisez readarray :

 readarray -t LINES < "$FILE" for LINE in "${LINES[@]}"; do ... done 

Remarque: Il n'est pas nécessaire de réinitialiser la valeur de l' IFS (c'est-à-dire IFS= read ) en n'utilisant qu'un seul paramètre.

Une autre option est xargs .

Avec GNU xargs :

 < file xargs -I{} -d'\n' command --option {} other args 

{} est le titulaire de la ligne de text.

D'autres xargs n'ont pas -d , mais certains ont -0 pour une input délimitée par NUL. Avec ceux-ci, vous pouvez faire:

 < file tr '\n' '\0' | xargs -0 -I{} command --option {} other args 

Sur les systèmes conforms à Unix ( -I est optionnel dans POSIX et uniquement requirejs pour les systèmes conforms à Unix), vous devez prétraiter l'input pour citer les lignes au format attendu par xargs :

 < file sed 's/"/"\\""/g;s/.*/"&"/' | xargs -E '' -I{} command --option {} other args 

Notez cependant que certaines implémentations de xargs ont une limite très faible sur la taille maximale de l'argument (255 sur Solaris par exemple, minimum autorisé par la spécification Unix).

  sed "s/'/'\\\\''/g;s/.*/\$* '&'/" <<\FILE |\ sh -s -- command echo --option all of the{&}se li$n\es 'are safely shell quoted and handed to command as its last argument following --option, and, here, before that echo FILE 

SORTIE

 --option all of the{&}se li$n\es 'are safely shell --option quoted and handed to command as its last argument --option following --option, and, here, before that echo 

Garder précisément à la question:

 #!/bin/bash # xargs -n param sets how many lines from the input to send to the command # Call command once per line [[ -f $1 ]] && cat $1 | xargs -n1 command --option # Call command with 2 lines as args, such as an openvpn password file # [[ -f $1 ]] && cat $1 | xargs -n2 command --option # Call command with all lines as args # [[ -f $1 ]] && cat $1 | xargs command --option 

La meilleure réponse que j'ai trouvée est:

 for i in `cat`; do $cmd $i; done < $file 
 ed file.txt %g/^/s// / 2,$g/^/-,.j 1s/^/command/ wq chmod 755 file.txt ./file.txt 

Prenez toutes les lignes d'un file et transmettez-les comme arguments à une seule command, c'est-à-

 command line1 line2 line3 .... 

Si vous avez besoin du drapeau --option pour faire précéder chaque ligne, changez la deuxième command pour:

 %g/^/s// --option /