Bash test command

In Bash scripting, the test command is a fundamental tool used to evaluate conditions and make decisions based on those conditions.
Bash test command

On this page

In Bash scripting, the test command is a fundamental tool used to evaluate conditions and make decisions based on those conditions. Whether you're checking if a file exists, comparing strings, or validating numeric values, the test command plays a crucial role in controlling the flow of your script. In this article, you'll learn how to use the test command effectively, with practical examples to help you apply it in real-world scenarios.

What is the test Command?

The test command in Bash is used to evaluate expressions and return a status code. A status code of 0 indicates that the expression is true, while a non-zero status code indicates false. The test command can be used in three different syntaxes, each with its own advantages:

Using the test Keyword

The most straightforward way to use test is by directly invoking the test command:

test EXPRESSION
FILE=/etc/app/config
if test -f "$FILE"; then
    echo "$FILE exists."
fi

This form is available in all POSIX-compliant shells and is the most portable across different Unix-like systems. It evaluates the given expression and returns a status code indicating whether the expression is true (0) or false (non-zero).

Using Square Brackets [ ]

A more common and readable shorthand for the test command is to use single square brackets:

[ EXPRESSION ]
if [ -f "$FILE" ]; then
    echo "The file exists."
fi

This form is functionally identical to using the test keyword but is often preferred for its simplicity and readability. It’s widely supported and typically used in conditional statements within Bash scripts.

Using Double Square Brackets [[ ]]

Double square brackets [[ ]] are an extended version of the test command available in Bash and some other modern shells like Zsh and Ksh. This syntax provides additional features and more flexibility compared to single square brackets:

[[ EXPRESSION ]]

Key Features of [[ ]]:

  • No Word Splitting or Filename Expansion: Because [[ ]] is built into the shell and doesn’t have legacy requirements, you don’t need to worry about word splitting based on the IFS variable. This means that variables evaluating to strings with spaces won’t be split unexpectedly, so you don’t need to put variables in double quotes as you would with single brackets:

String Comparison: [[ ]] can also handle more advanced string comparison, including lexicographical comparisons:

if [[ "$STRING1" > "$STRING2" ]]; then
    echo "$STRING1 is greater than $STRING2"
fi

Logical Operators: The && (AND) and || (OR) operators are built into the [[ ]] syntax, allowing you to combine multiple conditions more cleanly without needing to nest them.

if [[ -f "$FILE" && -r "$FILE" ]]; then
    echo "The file exists and is readable."
fi

Pattern Matching with =~: Unlike single square brackets, [[ ]] allows you to use regular expressions for pattern matching. For example:

if [[ $STRING =~ ^[A-Za-z]+$ ]]; then
    echo "The string contains only letters."
fi

This example checks if the string contains only letters using a regular expression.

This additional functionality makes [[ ]] more powerful and flexible, especially for complex conditions in scripts. However, it’s important to note that [[ ]] is not POSIX-compliant and may not be available in all Unix-like environments, so it’s best used when you’re certain that your script will be run in a Bash or similar modern shell environment.

To learn more about the difference between test, [ and [[ check out this article.

Using the test Command: Practical Examples

Now that you know what the test command is, let's look at some examples of using it in practice. Throughout these examples, we’ll use the [ ] syntax, which is commonly used and easy to read.

Checking File Existence

One of the most common uses of the test command is to check whether a file or directory exists. This is particularly useful when your script depends on certain files being present.

Check if a directory exists:The -d flag is used to verify that the specified path is a directory.

DIRECTORY=/etc
if [ -d "$DIRECTORY" ]; then
    echo "$DIRECTORY is a directory."
fi

Check if a regular file exists:The -f flag specifically checks for regular files, excluding directories and other types of files.

if [ -f "$FILE" ]; then
    echo "$FILE is a regular file."
fi

Check if a file exists:The -e flag checks if the file exists, regardless of its type (regular file, directory, socket, etc.).

FILE=/etc/passwd
if [ -e "$FILE" ]; then
    echo "$FILE exists."
fi

Using Logical Operators

The test command can be combined with logical operators to evaluate multiple conditions, making it more versatile in your scripts.

Negation:The ! operator negates the condition, allowing you to check if a file does not exist:

if [ ! -f /etc/nonexistent ]; then
    echo "The file does not exist."
fi

OR condition:To check whether at least one of the specified files exists, use the || operator:

if [ -f /etc/passwd ] || [ -f /etc/shadow ]; then
    echo "At least one file exists."
fi

AND condition:To check whether both files exist, you can use the && operator:

if [ -f /etc/passwd ] && [ -f /etc/hosts ]; then
    echo "Both files exist."
fi

Additional Practical Examples

Here are a few more examples that demonstrate how the test command can be used for various checks:

Check if a file has a non-zero size:This is useful for verifying that a file is not empty before proceeding with operations that depend on its content:

if [ -s "$FILE" ]; then
    echo "$FILE has a non-zero size."
fi

Check if a symbolic link exists:The -L flag checks if the specified path is a symbolic link:

LINK=/usr/bin/python
if [ -L "$LINK" ]; then
    echo "$LINK is a symbolic link."
fi

Check if a file is readable and writable:This ensures that the file can be both read and modified by the script:

if [ -r "$FILE" ] && [ -w "$FILE" ]; then
    echo "$FILE is readable and writable."
fi

Ensuring Configuration Files Are Present

Imagine you have a script that depends on certain configuration files. You can use the test command to ensure these files exist before proceeding:

CONFIG=/etc/myapp/config.cfg
if [ -f "$CONFIG" ]; then
    echo "Configuration file found, proceeding with setup..."
else
    echo "Error: Configuration file not found!"
    exit 1
fi

If the configuration file does not exist, the script will terminate with an error message.

File Test Operators

The test command provides a variety of operators that allow you to check specific attributes of files. These operators help you determine not just the existence of a file, but also its type, permissions, and other characteristics. Here’s a list of the most commonly used file test operators:

  • -b FILE: Returns true if the file exists and is a special block device (e.g., a disk).
  • -c FILE: Returns true if the file exists and is a special character device (e.g., a terminal or printer).
  • -d FILE: Returns true if the file exists and is a directory.
  • -e FILE: Returns true if the file exists, regardless of its type (regular file, directory, socket, etc.).
  • -f FILE: Returns true if the file exists and is a regular file (not a directory or device).
  • -G FILE: Returns true if the file exists and has the same group ownership as the user running the command.
  • -h FILE or L FILE: Returns true if the file exists and is a symbolic link.
  • -g FILE: Returns true if the file exists and has the set-group-ID (sgid) bit set.
  • -k FILE: Returns true if the file exists and has the sticky bit set.
  • -O FILE: Returns true if the file exists and is owned by the user running the command.
  • -p FILE: Returns true if the file exists and is a named pipe (FIFO).
  • -r FILE: Returns true if the file exists and is readable by the user running the command.
  • -S FILE: Returns true if the file exists and is a socket.
  • -s FILE: Returns true if the file exists and has a non-zero size (i.e., it is not empty).
  • -u FILE: Returns true if the file exists and has the set-user-ID (suid) bit set.
  • -w FILE: Returns true if the file exists and is writable by the user running the command.
  • -x FILE: Returns true if the file exists and is executable by the user running the command.

Conclusion

The test command plays a crucial role in Bash scripting, enabling you to evaluate conditions and make decisions within your scripts. By understanding how to use it to check file existence, compare strings, and assess other conditions, you can write scripts that are both dependable and adaptable to different scenarios.

Subscribe to sysxplore newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox. It's free!
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!