How to Check if a File or Directory Exists on Bash

Introduction

Before we begin talking about how to check if a file or directory exists on Bash, let's briefly understand – What is a Bash ?

Bash, short for "Bourne Again SHell," is a command-line shell and scripting language commonly used in Unix-based operating systems.

When writing Shell scripts, you'll frequently come into situations where you need to perform an action based on whether a file exists. The test command in Bash can be used to discover whether a file exists and what kind it is.

One of the following syntax forms is used for the test command:

test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

You should use the old test [ command, which is accessible on all POSIX shells, if you want your script to be portable. On most recent systems with Bash, Zsh, or Ksh as the default shell, the new enhanced version of the test command [[ (double brackets) is supported.

In this tutorial, you will check if a file or directory exists in Bash. We will also address a few FAQs on how to check if a file or directory exists in Bash.

Advantages of Bash

  1. Versatility: Bash is widely compatible and can run on various operating systems, making it a versatile choice for shell scripting.
  2. Powerful scripting: Bash provides robust scripting capabilities, allowing users to automate tasks, create complex workflows, and improve productivity.
  3. Command-line efficiency: With Bash, users can execute commands directly in a terminal, enabling quick and efficient interaction with the operating system.
  4. Process control: Bash offers excellent process management, allowing users to manage running processes, control input/output, and handle signals.
  5. Extensibility: Bash can be extended with custom scripts and functions, providing flexibility to tailor the shell to specific needs and preferences.

Check if File Exists

The FILE operators -e and -f are the most typically used when testing if a file exists. The first will check for the existence of a file regardless of its type, whereas the second will only return true if the FILE is a standard file (not a directory or a device).

When checking whether a file exists or not, the test command in conjunction with the if statement is the most readable approach. Any of the following snippets will check for the existence of the /etc/resolv.conf file:

FILE=/etc/resolv.conf
if test -f "$FILE"; then
    echo "$FILE exists."
fi
FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exists."
fi
FILE=/etc/resolv.conf
if [[ -f "$FILE" ]]; then
    echo "$FILE exists."
fi

Simply use the if/then construct to conduct a separate action based on whether the file exists:

FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exists."
else 
    echo "$FILE does not exist."
fi
💡
When dealing with files with whitespace in their names, always use double quotes to avoid problems.

The test command can also be used without the if statement. Only if the test command's exit status is true will the command after the && operator be executed.

test -f /etc/resolv.conf && echo "$FILE exists."
[ -f /etc/resolv.conf ] && echo "$FILE exists."
[[ -f /etc/resolv.conf ]] && echo "$FILE exists."

Simply encapsulate the commands in curly brackets separated by ; or && to run a succession of commands after the && operator.

[ -f /etc/resolv.conf ] && { echo "$FILE exist."; cp "$FILE" /tmp/; }

In contrast to &&, the statement after the || operator is only executed if the test command's exit status is false.

[ -f /etc/resolv.conf ] && echo "$FILE exist." || echo "$FILE does not exist."

Check if the Directory Exists

You can use the -d operator to determine whether or not a file is a directory.

To see if the /etc/docker directory exists, for example, use the following command:

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

You can also use the double brackets [[ instead of a single one [.

Check if the File does Not Exist

The logical not-operator ! (exclamation mark) can be used to negate the test expression, as it can in many other languages:

FILE=/etc/docker
if [ ! -f "$FILE" ]; then
    echo "$FILE does not exist."
fi

Same as above:

[ ! -f /etc/docker ] && echo "$FILE does not exist."

Check if Multiple Files Exist

To test if many files exist, use -a (or && with [[) instead of cumbersome nested if/else constructs:

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

Variants that are equivalent without utilizing the IF statement:

[ -f /etc/resolv.conf -a -f /etc/hosts ] && echo "Both files exist."
[ -f /etc/resolv.conf -a -f /etc/hosts ] && echo "Both files exist."

File test operators

The test command includes the FILE operators listed below, which allow you to test for certain file types:

  • -b FILE - True if the FILE is a special block file and exists.
  • -c FILE - True if the FILE is a special character file and exists.
  • -d FILE - If the FILE exists and is a directory, it returns true.
  • -e FILE - Returns true if the FILE exists and is a file of any type (node, directory, socket, etc.).
  • -f FILE - If the FILE exists and is a regular file, it returns true (not a directory or device).
  • -G FILE - If the FILE exists and belongs to the same group as the user running the command, this option is true.
  • -h FILE - If the FILE exists and is a symbolic link, it returns true.
  • -g FILE - If the FILE exists and the set-group-id (sgid) flag is set, it returns true.
  • -k FILE - If the FILE exists and has the sticky bit flag set, it returns true.
  • -L FILE - True if the FILE is a symbolic link and exists.
  • -O FILE - True if the FILE exists and is owned by the command's user.
  • -p FILE - If the FILE exists and is a pipe, it returns true.
  • -r FILE - Returns true if the FILE exists and can be read.
  • -S FILE - If the FILE exists and is a socket, it returns true.
  • -s FILE - Returns true if the FILE exists and has a size greater than zero.
  • -u FILE - If the FILE exists and the set-user-id (suid) flag is set and it returns true.
  • -w FILE - Returns true if the FILE exists and is writable.
  • -x FILE - Returns true if the FILE is present and executable.

FAQs to Check if a File or Directory Exists in Bash

How can I use the existence check in a script? 

You can use an if statement to conditionally check for existence within a Bash script. Example: if [ -e /path/to/file.txt ]; then echo "Exists!"; fi.

What if I want to perform an action if a file or directory does not exist?

Use the ! operator with an if statement to perform actions when it does not exist. Example: if [ ! -e /path/to/file.txt ]; then echo "Does not exist!"; fi.

Are there other types of checks available?

Yes, the test command supports various flags for different checks, such as identifying symbolic links, devices, permissions, and more.

Is there a shorthand version of the check? 

Yes, you can use double brackets in Bash as a shorthand. Example: [[ -e /path/to/file.txt ]].

Can I combine existence checks with other conditions? 

Yes, you can combine them with logical operators like && (AND) or || (OR) for more complex conditional checks in scripts. Example: if [ -f file.txt ] && [ -d directory ]; then echo "Both exist!"; fi.

How can I handle a scenario where a file or directory doesn't exist? 

You can add an else clause to the if statement like if [ -e /path/to/file ]; then <actions>; else <fallback actions>; fi to handle non-existent files or directories.

Can I combine existence checks with other conditions? 

Yes, you can use logical operators like && (AND) and || (OR) to combine existence checks with other conditions within if statements for more complex evaluations in Bash scripts.

Conclusion

We've taught you how to check if a file or directory exists in Bash in this post.

If you have any queries, please leave a comment below and we’ll be happy to respond to them.