tags:

views:

131

answers:

2

I currently use this function to wrap executing commands and logging their execution, and return code, and exiting in case of a non-zero return code.

However this is problematic as apparently, it does double interpolation, making commands with single or double quotes in them break the script.

Can you recommend a better way?

Here's the function:

do_cmd()
{
    eval $*
    if [[ $? -eq 0 ]]
    then
        echo "Successfully ran [ $1 ]"
    else
        echo "Error: Command [ $1 ] returned $?"
        exit $?
    fi
}
+4  A: 
"$@"

From http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters:

@ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" .... If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed).

This means spaces in the arguments are re-quoted correctly.

do_cmd()
{
    "$@"
    if [[ $? -eq 0 ]]
    then
        echo "Successfully ran [ $1 ]"
    else
        echo "Error: Command [ $1 ] returned $?"
        exit $?
    fi
}
Douglas Leeder
nice. beat me in time :p
Johannes Schaub - litb
+2  A: 

Additional to "$@" what Douglas says, i would use

return $?

And not exit. It would exit your shell instead of returning from the function. If in cases you want to exit your shell if something went wrong, you can do that in the caller:

do_cmd false i will fail executing || exit
# commands in a row. exit as soon as the first fails
do_cmd one && do_cmd && two && do_cmd three || exit

(That way, you can handle failures and then exit gracefully).

Johannes Schaub - litb