2

Sample bash script where I'm testing using variable expansion in command names:

test_command_w_variable_expansion_in_name.sh:

#!/bin/bash

# Gabriel Staples
# 21 Mar. 2020

echo "PATH = \"$PATH\""
# PATH="$HOME/bin:$PATH"
# echo "PATH = \"$PATH\""

# 1st, create a command in ~/bin to test here
mkdir -p ~/bin
echo -e "#!/bin/bash\necho \"This is a test script found in ~/bin.\"" > ~/bin/gs_test_script
chmod +x ~/bin/gs_test_script

# 1)
# command: `echo`
CMD_PREFIX="ec"

${CMD_PREFIX}ho "hey" # works
# exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!
# eval "${CMD_PREFIX}ho" "hey" # does NOT work, but also throws no error

# 2)
# command: `gs_test_script` from ~/bin
CMD_PREFIX="gs_test"

~/bin/gs_test_script # works!
gs_test_script # works!
${CMD_PREFIX}_script # works!

Output:

$ ./test_command_w_variable_expansion_in_name.sh
PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
hey
This is a test script found in ~/bin.
This is a test script found in ~/bin.
This is a test script found in ~/bin.

Questions:

  1. Now, if I uncomment this line: # exec "${CMD_PREFIX}ho" "hey" # works, but then prevents the code below from running!, the code below it no longer runs, and I get this output instead! Notice I no longer get the 3 printouts of This is a test script found in ~/bin. Why?

    $ ./test_command_w_variable_expansion_in_name.sh
    PATH = "/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
    hey
    hey
    
  2. Also, the eval command just below it doesn't work. If I uncomment out that line I get the exact same erroneous output as posted just above, which still doesn't execute my call to gs_test_script three times like it should. Why?

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • Don't use either `exec` or `eval` unless you understand what they do. `eval` in particular has a bad reputation for causing really weird (and sometimes dangerous) bugs. Putting commands (or parts of commands) in variables is also tricky to get right, and you're better off avoiding it if possible. See [BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!](http://mywiki.wooledge.org/BashFAQ/050) – Gordon Davisson Mar 22 '20 at 03:35

1 Answers1

2

Because the exec command will replace the current bash process with the new command to be executed. It does not return to the calling process. So you should not use exec in your script.

exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.
    
    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.
    
    Options:
      -a name   pass NAME as the zeroth argument to COMMAND
      -c    execute COMMAND with an empty environment
      -l    place a dash in the zeroth argument to COMMAND
    
    If the command cannot be executed, a non-interactive shell exits, unless
    the shell option `execfail' is set.
    
    Exit Status:
    Returns success unless COMMAND is not found or a redirection error occurs.
Changbin Du
  • 501
  • 5
  • 11
  • Where did you copy this from? I see it neither in `man exec`, `info exec`, nor `exec --help`. – Gabriel Staples Mar 22 '20 at 04:27
  • 1
    For bash builtins, use `help`: `help exec` – that other guy Mar 22 '20 at 05:07
  • My output from `help exec` is not the same as what is shown above. Perhaps we have different versions. The version shown at the top when I run just `help` is `GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)`. I'm on Ubuntu 18.04. @Changbin Du, what version of GNU bash are you running? Did you get that output from `help exec`? – Gabriel Staples Mar 22 '20 at 05:22
  • 1
    @Gabriel: It's bash 3.2.something, a throwback to 2007, as found on OS X (because they don't like the licensing for bash 4 and above). (And yes it comes from `help exec`) – rici Mar 22 '20 at 07:35