0

I'd like to write a script that reads a file and passes every line as options (or "option arguments") to a command, like this:

command -o "1st line" -o "2nd line" ... -o "last line" args

What's the simplest way of doing this?

0

Here is one possibility:

$ cat tmp
1st line
2nd line
3rd line
4th line
$ command $(sed 's|.*|-o "&"|' tmp | tr '\n' ' ')

As glennjackman points out in the comments, word splitting can be circumvented by wrapping in eval, though the security implications of doing so should be appreciated:

$ eval "command $(sed 's|.*|-o "&"|' tmp | tr '\n' ' ')"

Edit: Combining my suggestion of using sed to assemble arguments with glenn jackman's mapfile/readarray approach gives the following concise form:

$ mapfile -t args < <(sed 's|.*|-o\n&|' tmp) && command "${args[@]}"

As a trivial demonstration, consider the aforementioned tmp file, the command grep, and the file text:

$ cat text
some text 1st line and
a 2nd nonmatching line
some more text 3rd line end
$ mapfile -t args < <(sed 's|.*|-e\n&|' tmp) && grep "${args[@]}" text
some text 1st line and
some more text 3rd line end
$ printf "%s\n" "${args[@]}"
-e
1st line
-e
2nd line
-e
3rd line
-e
4th line
  • Unfortunately, this will not maintain the lines as whole elements due to the shell's word splitting. Try where the command is printf "%s\n" -- instead of receiving 8 arguments (-o 1st line ...), this technique will give the command 12 arguments containing literal quote chars (-o "1st line" -o "2nd line" etc). You could do eval "command $(sed ...)" but that's nasty and fragile. – glenn jackman Nov 8 '17 at 20:41
  • @glennjackman: Agreed, eval would be needed to avoid the word splitting problem; your command array-based approach is better for general use. – user001 Nov 8 '17 at 21:05
5
# step 1, read the lines of the file into a shell array
mapfile -t lines < filename

# build up the command
cmd_ary=( command_name )
for elem in "${lines[@]}"; do
    cmd_ary+=( -o "$elem" )
done
cmd_ary+=( other args here )

# invoke the command
"${cmd_ary[@]}"
  • This. Although you'll want to maybe check the file for total number of lines (or other delimiter) so that you don't call your command with more arguments than it can handle - might want to read up on this (old) article and then check for newer references - in-ulm.de/~mascheck/various/argmax – ivanivan Nov 8 '17 at 22:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.