Search code examples
bashpipe

How can I use pipes in command stored in a variable?


Trying to use pipes in bash script. This works fine on my Linux shell but bash script errors out. What am I doing wrong?

  #!/bin/bash
  #some code
  cmd="cat file2 | grep ':'  | awk -F \":\" '{print \$1}' > pool_names"
  echo $cmd
  exec $cmd
 

I see this error

cat: invalid option -- 'F'
Try 'cat --help' for more information.

Solution

  • In the shell, a "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator. (See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01), while a pipeline is a sequence of one or more commands separated by the control operator '|' (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_02). When the shell sees the line exec $cmd it does not see the control operator |, so that is a simple command. (This has nothing to do with exec, and the same behavior will occur with any command.) It then expands the variables in the line and follows the rule the first field shall be considered the command name and remaining fields are the arguments for the command, so exec is called with a bunch of arguments. exec does not attempt to interpret the arguments as shell operators (perhaps you meant to use eval instead of exec), but just passes all the arguments on to cat.