Introduction
In system management and task automation, Bash scripts are an essential tool. Within these scripts, the ability to make conditions-based decisions is essential to create logical flows that are adapted to different situations. The commandtestand its conditional operators allow to evaluate expressions that return a state of truth or falsehood, which can then be used in structuresif, whileoruntil.
What is the test command?
The commandtestis a Bash build-in that evaluates an expression and returns an output code of zero when the expression is true and different from zero when it is false. Its basic syntax is:
test EXPRESIÓN
Although it can be written directly, it is more common to see its abbreviated shape with square brackets:
[ EXPRESIÓN ]
The square brackets are synonymous withtestand must be separated by spaces of both the opening and closing clasp.
File test operators
File operators allow to inspect the status of a file or directory. Some of the most used are:
-a FILE: true if FILE exists.-b FILE: true if FILE exists and is a special block.-c FILE: true if FILE exists and is a special character.-d FILE: true if FILE exists and is a directory.-e FILE: true if FILE exists (equivalent to-a).-f FILE: true if FILE exists and is a regular file.-g FILE: true if FILE exists and has the SGID bit activated.-h FILEor-L FILE: true if FILE exists and is a symbolic link.-p FILE: true if FILE exists and is a name pipe (FIFO).-r FILE: true if FILE exists and is legible.-s FILE: true if FILE exists and is larger than zero.-t FD: true if the FD file descriptor is open and refers to a terminal.-u FILE: true if FILE exists and has the SUID bit activated.-w FILE: true if FILE exists and is scribable.-x FILE: true if FILE exists and is executable.-O FILE: true if FILE exists and is the property of the effective user.-G FILE: true if FILE exists and belongs to the effective group.-k FILE: true if FILE exists and has the bit sticky activated.
Chain test operators
To work with text, Bash offers several operators that compare character chains:
STRING1 = STRING2: true if the chains are identical.STRING1 != STRING2: true if the chains differ.-z STRING: true if the length of STRING is zero (empty chain).-n STRING: true if the length of STRING is greater than zero.STRING: true if STRING is not empty (equivalent to-n STRING).
Whole test operators
The following operators are used when comparing numerical values:
INT1 -eq INT2: true if INT1 is equal to INT2.INT1 -ne INT2: true if INT1 is not equal to INT2.INT1 -lt INT2: true if INT1 is less than INT2.INT1 -le INT2: true if INT1 is less than or equal to INT2.INT1 -gt INT2: true if INT1 is greater than INT2.INT1 -ge INT2: true if INT1 is greater or equal to INT2.
Logical operators
To combine several tests you can use the logical operators:
! EXPRESIÓN: denial, reverse the result of the expression.EXPRESIÓN1 -a EXPRESIÓN2: AND logical, true if both expressions are true.EXPRESIÓN1 -o EXPRESIÓN2: OR logical, true if at least one expression is true.
Note: operators-aand-oare command specifictestand of single square brackets[ ]. In the double square brackets syntax[[ ]]are preferred&&and||.
Use of the test in sentences if
The most common pattern is to combinetestwith a conditional structure:
if test -f "$archivo"; then
echo "El archivo existe."
else
echo "El archivo no existe."
fi
Equivalent, using square brackets:
if [ -f "$archivo" ]; then
echo "El archivo existe."
else
echo "El archivo no existe."
fi
In both cases it is important to surround the variable between quotes to avoid problems with special spaces or characters.
Differences between [] and [[]]
Although the square brackets are simple[ ]are synonymous withtest, double square brackets[[ ]]are a key word of Bash that offers additional features:
- They do not require operators to be escaped (e.g.,
[[ $var == *pat* ]]works without backslashes). - They allow regular expressions with the operator
=~. - They avoid word division and file name expansion within the square brackets.
- They are more legible for logical combinations using
&&and||.
Example with regular expressions:
if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo "Dirección de correo válida."
else
echo "Dirección de correo no válida."
fi
Practical examples
Here are some scripts that illustrate the use oftestand its operators:
Check if a directory is scribable
#!/bin/bash
DIR="/var/log"
if [ -w "$DIR" ]; then
echo "El directorio $DIR es escribible."
else
echo "El directorio $DIR NO es escribible."
fi
Check if two numerical variables are the same
#!/bin/bash
A=15
B=20
if [ "$A" -eq "$B" ]; then
echo "A y B son iguales."
else
echo "A y B son diferentes."
fi
Validate that a parameter is not empty
#!/bin/bash
if [ -z "$1" ]; then
echo "Error: se requiere un argumento."
exit 1
else
echo "Argumento recibido: $1"
fi
Use AND and OR in one test
#!/bin/bash
if [ -f "$archivo" -a -r "$archivo" ]; then
echo "El archivo existe y es legible."
else
echo "Falta el archivo o no tiene permisos de lectura."
fi
Common tramps and good practices
- Always place spaces around the operators and inside the square brackets:
[ $var -eq 5 ]is correct;[$var-eq5]He'll fail. - Protect variables with double quotes to avoid word division and balloon expansion.
- Prefer
[[ ]]when regular patterns or expressions are needed, as it is safer and readable. - Remember that the allocation operator
=within[ ]is for chain comparison, not for assignment. - In contexts where you need to invest a test, use
!before expression or operator-not(although the latter is not standard in all versions).
Conclusion
The commandtestand its conditional operators are the basis for decision-making in Bash. Domain your syntax, know the different types of tests (file, chain, whole) and know how to combine them with logical operators allows you to write more robust, legible and sustainable scripts. Whether you are verifying the existence of a file, validating the user's input or creating complex workflows, the proper use oftestmake your scripts more reliable and professional.


