The question is pretty straight forward. I can get the exit code of the previous command by using $?. But what exactly is it?

I don't think it is a variable, because you can't have any special characters in the name of variable other than _.


will result in the error: foo?foo=10: command not found

So if it is not a variable, what is it? Are there others like it?


What is it?

$? is a built-in variable that stores the exit status of a command, function, or the script itself.

$? reads the exit status of the last command executed. After a function returns, $? gives the exit status of the last command executed in the function. This is Bash's way of giving functions a "return value." It returns 0 on success or an integer in the range 1 - 255 on error.

Are there others like it too?

Yes,there are several such built-in variables in bash. You can see a list here. Refer: http://www.tldp.org/LDP/abs/html/exit-status.html

  • 1
    So it's available in bash shell only? – daltonfury42 Jul 9 '15 at 18:59
  • 4
    @daltonfury42 no, any shell that attempts to have some compatibility with the Bourne shell will support it (including dash, ksh, zsh, among others). – muru Jul 9 '15 at 19:17
  • 2
    csh and fish use $status for the same purpose – glenn jackman Jul 9 '15 at 19:57

$? is a variable but a special one, that's why special characters are allowed. ($?) Expands to the exit status of the most recently executed foreground pipeline.

It's not the only one, the shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed :

Variable    Meaning
$0          Filename of script
$1          Positional parameter #1
$2 - $9     Positional parameters #2 - #9
${10}       Positional parameter #10
$#          Number of positional parameters
"$*"        All the positional parameters (as a single word) *
"$@"        All the positional parameters (as separate strings)
${#*}       Number of positional parameters
${#@}       Number of positional parameters
$?          Return value
$$          Process ID (PID) of script
$-          Flags passed to script (using set)
$_          Last argument of previous command
$!          Process ID (PID) of last job run in background

* Must be quoted, otherwise it defaults to $@.


  • 2
    "$*" is not just all positional parameters as a single word, but all positional parameters separated by the first character of IFS as a single word. Since the result will be subject to field splitting if not quoted, the effect is as if $@ is used in the unquoted case. – muru Jul 9 '15 at 19:20
  • 1
    To be sure: unquoted $@ and $* are the same because they are both subject to word splitting. Quoted, "$@" preserves the word splitting of the positional parameters, even if an individual parameter contains a character in IFS. – kojiro Jul 10 '15 at 3:26
  • 1
    Is there a reference of since when that is used for shells? I wonder if Perl took those from shell scripting. – simbabque Jul 10 '15 at 11:47
  • This predates Perl by decades (or at least years). A lot of the Perl syntax was influenced by shell syntax. (Perl was born in 1987, and a lot of this syntax came from the original Bourne shell (1977). I'm not 100% when $_ was introduced, but it was almost certainly well before 1987. – Popup Jul 10 '15 at 14:31

$? is a special shell parameter (variable).

In general all user defined variables must be named by using only the characters from character class [:alnum:] i.e. [a-zA-Z0-9_] (also can't begin with [0-9]).

In a nutshell, $? is a special variable (and there are quite a few of these) that can be considered as internal feature of the shell itself that provides the exit code of the previous command (whether succeded or failed).

You can read this to get more idea on variables.


$? is a special variable in bash that always holds the return/exit code of the last executed command.

You can view it in a terminal by running echo $?.

Return codes are in the range [0; 255].
A return code of 0 usually means everything is ok.
Other values indicate errors. Most applications return 1 or custom values. If a command was not found, the variable usually contains 127

If you want to set this variable to a specific value, you can easily do this with bash -c "exit 5" to return for example the return code 5.

  • A shell function is a POSIX compliant way to set the exit status without necessarily forking. setstatus() { return 5; } – kojiro Jul 10 '15 at 3:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.