How to parse each line of a text file as an argument to a command?

Another option is xargs.

With GNU xargs:

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

{} is the place holder for the line of text.

Other xargs generally don't have -a, -d, but some have -0 for NUL-delimited input. With those, you can do:

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

On Unix-conformant systems (-I is optional in POSIX and only required for UNIX-conformant systems), you'd need to preprocess the input to quote the lines in the format expected by xargs:

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

However note that some xargs implementations have a very low limit on the maximum size of the argument (255 on Solaris for instance, the minimum allowed by the Unix specification).


Use while read loop:

: > another_file  ## Truncate file.

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

Another is to redirect output by block:

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

Last is to open the file:

exec 4> another_file

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

If one of the commands reads input, it would be a good idea to use another fd for input so the commands won't eat it (here assuming ksh, zsh or bash for -u 3, use <&3 instead portably):

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

Finally to accept arguments, you can do:

#!/bin/bash

FILE=$1
ANOTHER_FILE=$2

exec 4> "$ANOTHER_FILE"

while IFS= read -ru 3 LINE; do
    command --option "$LINE" >&4
done 3< "$FILE"

Which one could run as:

bash script.sh file another_file

Extra idea. With bash, use readarray:

readarray -t LINES < "$FILE"

for LINE in "${LINES[@]}"; do
    ...
done

Note: IFS= can be omitted if you don't mind having line values trimmed of leading and trailing spaces.


Keeping precisely to the 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