Search code examples
bashcommand-substitutionindirectionshellcheckmultiple-indirection

Executing the output as filename


In one of my Bash scripts, there's a point where I have a variable SCRIPT which contains the /path/to/an/exe, and what the script ultimately needs to do, is executing that executable. Therefore the last line of the script is

$($SCRIPT)

so that $SCRIPT is expanded to /path/to/an/exe, and $(/path/to/an/exe) executes the executable.

However, running shellcheck on the script generates this error:

In setscreens.sh line 7:
$($SCRIPT)
^--------^ SC2091: Remove surrounding $() to avoid executing output.

For more information:
  https://www.shellcheck.net/wiki/SC2091 -- Remove surrounding $() to avoid e...

Is there a way I can rewrite that $($SCRIPT) in a more appropriate way? eval does not seem to be of much help here.


Solution

  • $($SCRIPT) indeed does not do what you think it does.

    The outer $() will execute any commands inside the parenthesis and execute the result string.

    The inner $SCRIPT will expand to the value of the SCRIPT variable and execute this string while splitting words on spaces/

    If you want to execute the command contained into the SCRIPT variable, you just write as an example:

    SCRIPT='/bin/ls'
    "$SCRIPT" # Will execute /bin/ls
    

    Now if you also need to handle arguments with your SCRIPT variable command call:

    SCRIPT='/bin/ls'
    "$SCRIPT" -l # Will execute /bin/ls -l
    

    To also store or build arguments dynamically, you'd need an array instead of a string variable.

    Example:

    SCRIPT=(/bin/ls -l)
    "${SCRIPT[@]}" # Will execute /bin/ls -l
    
    SCRIPT+=(/etc) # Add /etc to the array
    "${SCRIPT[@]}" # Will execute /bin/ls -l /etc