return value from eval

22,349

Solution 1

When you do the following -

`nonsense`
echo $?

You basically are asking "Tell me the exit status when I try to get the output of the command nonsense" the answer to that is "command not found" or 127

But when you do the following

eval `nonsense`
echo $?

You are asking "tell me the exit status of eval when I evaluate an empty string" (the output of command nonsense) which is equal to running eval without arguments.

eval has no problems in running without arguments and its exit status becomes 0

Solution 2

Actually, it's more the:

$ `nonsense`
bash: nonsense: command not found
$ echo "$?"
127

That is surprising here.

We're asking bash to run the command that results of the split+glob operator on the stdout of nonsense. Since nonsense produces no output, it runs no command, so you may think the exit status should be 0.

But actually, when a simple command line has no argument, only assignment or redirection, the exit status is that of the last command substitution in assignment and normal words (not in redirection targets) that was run (though failure in redirections will also affect the exit status).

That's specially useful with assignments.

In:

output=$(grep pattern file)
status=$?

You can get both the output and exit status of grep, which you couldn't do if $? was otherwise the exit status of that non-command.

In:

output=$(cmd1) cmd2

That is where there are both assignment words and argument words, the exit status of cmd1 is ignored. $? will contain the exit status of cmd2.

And, also $output will only be set for cmd2 only. Exception to that is when cmd2 is a special builtin.

eval is such a special builtin.

$ a=0; a=1 eval; echo "$a"
1

In bash and most modern POSIX shells.

a=`exit 5` eval; echo "$?"

or

eval `exit 5`; echo "$?"

Would output 0, as it's the result of running eval with no argument. But that was not the case in the Bourne shell or ksh88, where for special builtins you'd get the exit status of exit 5 there.

In those shells, you'll also find:

$ a=`exit 3` set x; echo "$?"
3

As set is another special builtin.

. is another special builtin. In the Bourne shell and ksh88:

$ . /some/file `exit 4`; echo "$?"
4

(as long as /some/file doesn't run any command)

Share:
22,349
Viesturs
Author by

Viesturs

Updated on September 18, 2022

Comments

  • Viesturs
    Viesturs almost 2 years

    The bash manual states:

    eval [arg ...]
    
              The  args  are read and concatenated together into a single com-
              mand.  This command is then read and executed by the shell,  and
              its  exit status is returned as the value of eval. If there are
              no args, or only null arguments, eval returns 0.
    

    I try

    eval `nonsense`
    echo $?
    

    The result is 0.

    Whereas when I execute the back-quoted command separately:

    `nonsense`
    echo $?
    

    The result is 127.

    From what is written in the bash manual I would expect eval to return 127 when taking the back-quoted nonsense as argument.

    How to obtain the exit status of the argument of eval?

    • Ignacio Vazquez-Abrams
      Ignacio Vazquez-Abrams over 6 years
      `nonsense` doesn't return anything if nonsense doesn't exist, so there are no arguments to eval.
    • Weijun Zhou
      Weijun Zhou over 6 years
      You should run eval nonsense, then you will get 127.
    • Viesturs
      Viesturs over 6 years
      @WeijunZhou, for the specific case at hand nonsense comes in back-quotes,
    • Weijun Zhou
      Weijun Zhou over 6 years
      OK, I upvoted it because it has provided some insight to the problem.
  • Charles Duffy
    Charles Duffy over 6 years
    Code formatting should not be used for English prose.
  • amisax
    amisax over 6 years
    @CharlesDuffy .. thanks for the edit tip, made the changes accordingly
  • codenoob
    codenoob over 4 years
    I'm confused. The OP provided context, and that is what is being responded to, but where is the answer to the actual question posited which was: "How to obtain the exit status of the argument of eval?" I guess I need to read more carefully?
  • codenoob
    codenoob over 4 years
    I'm confused. The OP provided context, and that is what is being responded to, but where is the answer to the actual question posited which was: "How to obtain the exit status of the argument of eval?" I guess I need to read more carefully?