Search code examples
bashbash-function

Bash function not executing the input command


In a bash file s.sh, I have an Executor function to which I pass the commands to be executed. Whenever some command does not work as expected, this function outputs the command.

Executor()
{
    if ! $*
    then
        echo "$*"
        exit 2
    fi
}

Now I am invoking this function -

Executor clangPath="Hello" make (This is used to set the value of clangPath variable as "Hello" in the makefile)

This caused an error -

./s.sh: line 5: clangPath=Hello: command not found
[./s.sh] Error: clangPath=Hello make

However executing the same command like this works fine

if ! clangPath="Hello" make
then
    echo "HelloWorld!"
fi

After looking at the error, I thought there might be a mistake with the string quotations, so I tried

exitIfFail clangPath='"Hello"' make

Even this resulted in an error -

./s.sh: line 5: clangPath="Hello": command not found
[./s.sh] Error: clangPath="Hello" make

What could be the reason for the error?


Solution

  • If the purpose of the function is to execute some Bash expression, then print an error message, if the expression failed (returned non-zero status), then, there is a way to implement this via eval:

    #!/bin/bash -
    
    function Executor()
    {
      eval "$@"
    
      if [ $? -ne 0 ]
      then
        echo >&2 "Failed to execute command: $@"
        exit 2
      fi
    }
    

    The $? variable holds the exit status of the previously executed command. So we check if it is non-zero.

    Also note how we redirect the error message to the standard error descriptor.

    Usage:

    Executor ls -lh /tmp/unknown-something
    ls: cannot access /tmp/unknown-something: No such file or directory
    Failed to execute command: ls -lh /tmp/unknown-something
    
    
    Executor ls -lh /tmp
    # some file listing here...
    

    The $@ variable is more appropriate here, as eval interprets things itself. See $* and $@.