I'm trying to learn shell scripting, and I need to understand someone else's code. What is the $?
variable hold? I can't Google search the answer because they block punctuation characters.

- 347,512
- 102
- 1,199
- 985

- 7,595
- 11
- 45
- 61
-
101A good google search turns out to be "bash dollar question mark" – frankc Jul 26 '11 at 19:03
-
13SymbolHound works well for searches involving special characters. Example: http://symbolhound.com/?q=%24%3F – Anssssss May 07 '13 at 17:54
-
1`info bash` also works, but unfortunately you can't just search for "$?", since the documentation omits the `$`. Go to the "Special Parameters" section (3.4.2 as of version 4.2) or search for backtick-`\$'` (you have to escape the `?` because the search term is a regular expression). (I'm sure there's a way to put a literal backtick in a comment.) – Keith Thompson Aug 04 '13 at 20:59
-
26That moment when googling "bash dollar question mark" brings this SO Question as first result. Don't blame us. – Dumoko Nov 10 '14 at 08:18
-
1@KeithThompson You probably know this by now, but you can escape it with `\\` (so you end up writing `\\\`` to get the backtick) (and `\\\\\\\`` to get what I just wrote) – Nic Jan 08 '16 at 19:23
9 Answers
$?
is used to find the return value of the last executed command.
Try the following in the shell:
ls somefile
echo $?
If somefile
exists (regardless whether it is a file or directory), you will get the return value thrown by the ls
command, which should be 0
(default "success" return value). If it doesn't exist, you should get a number other then 0. The exact number depends on the program.
For many programs you can find the numbers and their meaning in the corresponding man page. These will usually be described as "exit status" and may have their own section.

- 4,888
- 3
- 23
- 27
-
15
-
12
-
1
-
So `man $?` is your friend to get the exit status. Invoking `((1==2));echo $?` returns 1 in bash. – Timo Sep 09 '20 at 15:38
That is the exit status of the last executed function/program/command. Refer to:

- 7,344
- 4
- 32
- 45
Minimal POSIX C exit status example
To understand $?
, you must first understand the concept of process exit status which is defined by POSIX. In Linux:
when a process calls the
exit
system call, the kernel stores the value passed to the system call (anint
) even after the process dies.The exit system call is called by the
exit()
ANSI C function, and indirectly when you doreturn
frommain
.the process that called the exiting child process (Bash), often with
fork
+exec
, can retrieve the exit status of the child with thewait
system call
Consider the Bash code:
$ false
$ echo $?
1
The C "equivalent" is:
false.c
#include <stdlib.h> /* exit */
int main(void) {
exit(1);
}
bash.c
#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */
int main(void) {
if (fork() == 0) {
/* Call false. */
execl("./false", "./false", (char *)NULL);
}
int status;
/* Wait for a child to finish. */
wait(&status);
/* Status encodes multiple fields,
* we need WEXITSTATUS to get the exit status:
* http://stackoverflow.com/questions/3659616/returning-exit-code-from-child
**/
printf("$? = %d\n", WEXITSTATUS(status));
}
Compile and run:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o bash bash.c
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o false false.c
./bash
Output:
$? = 1
In Bash, when you hit enter, a fork + exec + wait happens like above, and bash then sets $?
to the exit status of the forked process.
Note: for built-in commands like echo
, a process need not be spawned, and Bash just sets $?
to 0 to simulate an external process.
Standards and documentation
POSIX 7 2.5.2 "Special Parameters" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :
? Expands to the decimal exit status of the most recent pipeline (see Pipelines).
man bash
"Special Parameters":
The shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed. [...]
? Expands to the exit status of the most recently executed foreground pipeline.
ANSI C and POSIX then recommend that:
0
means the program was successfulother values: the program failed somehow.
The exact value could indicate the type of failure.
ANSI C does not define the meaning of any vaues, and POSIX specifies values larger than 125: What is the meaning of "POSIX"?
Bash uses exit status for if
In Bash, we often use the exit status $?
implicitly to control if
statements as in:
if true; then
:
fi
where true
is a program that just returns 0.
The above is equivalent to:
true
result=$?
if [ $result = 0 ]; then
:
fi
And in:
if [ 1 = 1 ]; then
:
fi
[
is just an program with a weird name (and Bash built-in that behaves like it), and 1 = 1 ]
its arguments, see also: Difference between single and double square brackets in Bash

- 1
- 1

- 347,512
- 102
- 1,199
- 985
A return value of the previously executed process.
10.4 Getting the return value of a program
In bash, the return value of a program is stored in a special variable called $?.
This illustrates how to capture the return value of a program, I assume that the directory dada does not exist. (This was also suggested by mike)
#!/bin/bash cd /dada &> /dev/null echo rv: $? cd $(pwd) &> /dev/null echo rv: $?
See Bash Programming Manual for more details.
-
For a moment, I thought `rv:` was some sort of old style options list, but it turns out just to be text which is echoed. – Joe Jul 15 '15 at 20:24
$?
is the exit status of a command, such that you can daisy-chain a series of commands.
Example
command1 && command2 && command3
command2
will run if command1's
$?
yields a success (0)
and command3
will execute if $?
of command2
will yield a success

- 7,773
- 14
- 36
- 45

- 51
- 1
- 3