Bash - Tests¶
Objectives: In this chapter you will learn how to:
work with the return code;
test files and compare them;
test variables, strings and integers;
perform an operation with numeric integers;
linux, script, bash, variable
Reading time: 10 minutes
Upon completion, all commands executed by the shell return a return code (also called status or exit code).
- If the command ran correctly, the convention is that the status code will be zero.
- If the command encountered a problem during its execution, its status code will have a non-zero value. There are many reasons for this: lack of access rights, missing file, incorrect input, etc.
You should refer to the manual of the
man command to know the different values of the return code provided by the developers.
The return code is not visible directly, but is stored in a special variable:
mkdir directory echo $? 0
mkdir /directory mkdir: unable to create directory echo $? 1
command_that_does_not_exist command_that_does_not_exist: command not found echo $? 127
The display of the contents of the
$? variable with the
echo command is done immediately after the command you want to evaluate because this variable is updated after each execution of a command, a command line or a script.
Since the value of
$? changes after each command execution, it is better to put its value in a variable that will be used afterwards, for a test or to display a message.
ls no_file ls: cannot access 'no_file': No such file or directory result=$? echo $? 0 echo $result 2
It is also possible to create return codes in a script.
To do so, you just need to add a numeric argument to the
bash # to avoid being disconnected after the "exit 2 exit 123 echo $? 123
In addition to the correct execution of a command, the shell offers the possibility to run tests on many patterns:
- Files: existence, type, rights, comparison;
- Strings: length, comparison;
- Numeric integers: value, comparison.
The result of the test:
$?=0: the test was correctly executed and is true;
$?=1: the test was correctly executed and is false;
$?=2: the test was not correctly executed.
Testing the type of a file¶
Syntax of the
test command for a file:
test [-d|-e|-f|-L] file
[ -d|-e|-f|-L file ]
Note that there is a space after the
[ and before the
Options of the test command on files:
||Tests if the file exists|
||Tests if the file exists and is of normal type|
||Checks if the file exists and is of type directory|
||Checks if the file exists and is of type symbolic link|
||Checks if the file exists and is of special type block mode|
||Checks if the file exists and is of special type character mode|
||Checks if the file exists and is of type tube|
||Checks if the file exists and is of type socket|
||Checks if the file exists and is of type terminal|
||Checks if the file exists and is readable|
||Checks if the file exists and is writable|
||Checks if the file exists and is executable|
||Checks if the file exists and has a set SGID|
||Checks if the file exists and has a set SUID|
||Tests if the file exists and is non-empty (size > 0 bytes)|
test -e /etc/passwd echo $? 0 [ -w /etc/passwd ] echo $? 1
An internal command to some shells (including bash) that is more modern, and provides more features than the external command
test, has been created.
[[ -s /etc/passwd ]] echo $? 1
We will therefore use the internal command for the rest of this chapter.
Compare two files¶
It is also possible to compare two files:
[[ file1 -nt|-ot|-ef file2 ]]
||Tests if the first file is newer than the second|
||Tests if the first file is older than the second|
||Tests if the first file is a physical link of the second|
It is possible to test variables:
[[ -z|-n $variable ]]
||Tests if the variable is empty|
||Tests if the variable is not empty|
It is also possible to compare two strings:
[[ string1 =|!=|<|> string2 ]]
[[ "$var" = "Rocky rocks!" ]] echo $? 0
||Tests if the first string is equal to the second|
||Tests if the first string is different from the second one|
||Tests if the first string is before the second in ASCII order|
||Tests if the first string is after the second in ASCII order|
Comparison of integer numbers¶
Syntax for testing integers:
[[ "num1" -eq|-ne|-gt|-lt "num2" ]]
var=1 [[ "$var" -eq "1" ]] echo $? 0
var=2 [[ "$var" -eq "1" ]] echo $? 1
||Test if the first number is equal to the second|
||Test if the first number is different from the second|
||Test if the first number is greater than the second|
||Test if the first number is less than the second|
Since numeric values are treated by the shell as regular characters (or strings), a test on a character can return the same result whether it is treated as a numeric or not.
test "1" = "1" echo $? 0 test "1" -eq "1" echo $? 0
But the result of the test will not have the same meaning:
- In the first case, it will mean that the two characters have the same value in the ASCII table.
- In the second case, it will mean that the two numbers are equal.
The combination of tests allows you to perform several tests in one command. It is possible to test the same argument (file, string or numeric) several times or different arguments.
[ option1 argument1 [-a|-o] option2 argument 2 ]
ls -lad /etc drwxr-xr-x 142 root root 12288 sept. 20 09:25 /etc [ -d /etc -a -x /etc ] echo $? 0
||AND: The test will be true if all patterns are true.|
||OR: The test will be true if at least one pattern is true.|
With the internal command, it is better to use this syntax:
[[ -d "/etc" && -x "/etc" ]]
Tests can be grouped with parentheses
) to give them priority.
(TEST1 -a TEST2) -a TEST3
! character is used to perform the reverse test of the one requested by the option:
test -e /file # true if file exists ! test -e /file # true if file does not exist
expr command performs an operation with numeric integers.
expr num1 [+] [-] [\*] [/] [%] num2
expr 2 + 2 4
Be careful to surround the operation sign with a space. You will get an error message if you forget.
In the case of a multiplication, the wildcard character
* is preceded by
\ to avoid a wrong interpretation.
||Modulo of the division|
typeset -i command declares a variable as an integer.
typeset -i var1 var1=1+1 var2=1+1 echo $var1 2 echo $var2 1+1
let command tests if a character is numeric.
var1="10" var2="AA" let $var1 echo $? 0 let $var2 echo $? 1
let command does not return a consistent return code when it evaluates the numeric
let 0 echo $? 1
let command also allows you to perform mathematical operations:
let var=5+5 echo $var 10
let can be substituted by
echo $((5+2)) 7 echo $((5*2)) 10 var=$((5*3)) echo $var 15
Author: Antoine Le Morvan
Contributors: Steven Spencer