bashshellif-statement

How to assign the output of a command to a variable while checking if the command was successful?


I'm going to try my best to explain the question. Please don't hesitate to ask for clarification if needed.

Ultimately, I want

  1. to assign the output of a command to a variable while
  2. maintaining the possibility to check if the command was successful or not.

In the following code, ls is only an example. The command I'm going to use is different.

For the first part, normally, I would do something like this:

{
  ls nonexistingfolder
} && {
  echo "fine"
} || {
  echo "error"
}

However, above code doesn't work, when I'm using export to save the output to a variable:

{
  export MESSAGE=$(ls nonexistingfolder)
} && {
  echo "fine"
} || {
  echo "error"
}

Above code will always print fine.

I tried something with an if statement:

export MESSAGE=$(ls notexistingfolder)
if [ -z "$MESSAGE" ] ; then echo "error" ; else echo "fine" ; fi

But above code won't work when the command succeeds without output (for example if ls lists an empty folder):

export MESSAGE=$(ls emptyfolder)
if [ -z "$MESSAGE" ] ; then echo "error" ; else echo "fine" ; fi

Above code falsely prints error.

So I thought about defining an "error value" for $MESSAGE:

export MESSAGE=$(ls notexistingfolder || echo "error")
if [ "$MESSAGE" = "error" ] ; then echo "error" ; else echo "fine" ; fi

Above code prints error as it should.

export MESSAGE=$(ls emptyfolder || echo "error")
if [ "$MESSAGE" = "error" ] ; then echo "error" ; else echo "fine" ; fi

Above code prints fine as it should.

However, there is the low possibility that the command will succeed and return a string which matches my "error value" exactly (for example if ls lists a folder which contains a folder called error):

export MESSAGE=$(ls folderwitherrorfolder || echo "error")
if [ "$MESSAGE" = "error" ] ; then echo "error" ; else echo "fine" ; fi

Above code will falsely print error.

What can I do? Thank you! :-)


Solution

  • You can just

    MESSAGE=$(ls ...)
    if [[ $? -eq 0 ]]; then
      success
    else
      failure
    fi
    export MESSAGE
    

    Points:

    1. var=$(foo ...): the assignment would not change $? so $? is still the foo's exit code.
    2. export itself is a command so export var=$(foo ...)'s exit code would overwrite foo's exit code.

    There ARE scenarios (syntax errors; assigning to readonly vars; ...) where var=value may change $? and export may fail. Examples:

    [STEP 101] $ true
    [STEP 102] $ 
    [STEP 103] $ var=${:}
    bash: ${:}: bad substitution
    [STEP 104] $ echo $?
    1
    [STEP 105] $ export var=${:}
    bash: var=${:}: bad substitution
    [STEP 106] $ echo $?
    1
    [STEP 107] $