🎁 Give the #1 gift request of 2024... a ZTM membership gift card! 🎁

How To Check If A File Exists in Bash (With Code Examples)

Andrei Dumitrescu
Andrei Dumitrescu
hero image

Have you ever had a script crash right in the middle because it couldn’t find a file? Frustrating, isn’t it?

In DevOps, this can lead to bigger issues, especially if your script relies on that missing file to perform critical tasks. That’s why learning how to check if a file exists in Bash is more than just a nice-to-have skill - it’s essential.

The good news?

By adding one simple check to your script, you can save hours of troubleshooting. No more guesswork or wasted time tracking down why something broke.

With a simple file check in place, your scripts run smoothly, avoiding errors and preventing the headaches that come with debugging complex systems. Whether it’s for automated backups, managing config files, or running regular system checks, mastering this skill will make your Bash scripts run like clockwork.

In this guide, you’ll learn how to check if a file exists in Bash, handle different file types, and make sure your scripts can gracefully deal with missing files.

Sidenote: Want to dive deeper into Bash? Check out my complete BASH scripting course:

learn bash

You'll learn Shell Scripting fundamentals, master the command line, and get the practice and experience you need to go from beginner to being able to get hired as a DevOps Engineer, SysAdmin, or Network Engineer!

I guarantee that this is the most comprehensive and up-to-date online resource to learn Bash Scripting.

With that out of the way, let’s dive into this 5-minute tutorial…

How to check if a file exists using Bash conditionals

When you're writing a Bash script, one of the first things you'll want to know is if a file exists, as this can make or break the script, especially if the file is critical to its operation.

Thankfully, Bash gives you a simple way to check for a file with an if statement and the -e flag.

(If you're not familiar with how if statements work in Bash, check out my complete guide to Bash if statements for a deeper understanding.)

Here’s how you can do it:

#!/bin/bash
if [ -e /path/to/your/file ]; then
    echo "File exists."
else
    echo "File does not exist."
fi

What’s happening here?

The -e flag is doing the heavy lifting here. It checks whether the file or directory exists at the path you've specified, without distinguishing between the two. This makes it more general compared to -f (regular file) and -d (directory), which check for specific types.

If Bash finds the file, it runs the code in the then block, which in this case simply echoes that the file exists. If the file isn’t found, Bash jumps to the else block and lets you know the file isn’t there.

Cool right?

Now, to make sure this works smoothly in all situations, it’s a good idea to use absolute paths in your scripts. Relative paths can cause problems if the script runs from a different directory, and Bash may not find the file where you expect it to be. By sticking to absolute paths like /home/user/file.txt, you ensure Bash always knows where to look.

You’ll also want to keep an eye on permissions. A file might exist, but your script may not be able to read or write to it because of access issues. To avoid this, check the file’s permissions using -r for readable or -w for writable, and you won’t run into those frustrating “permission denied” errors.

For example

#!/bin/bash
if [ -r /path/to/your/file ]; then
    echo "File is readable."
else
    echo "File is not readable."
fi

if [ -w /path/to/your/file ]; then
    echo "File is writable."
else
    echo "File is not writable."
fi

In this example, the -r flag checks if the file is readable, and -w checks if it's writable. You can add these checks to ensure that your script has the proper access to the files it needs to work with.

This basic check sets you up for more complex file handling, helping you build scripts that can reliably handle files and avoid unexpected problems.

How to handle different file types and conditions

Sometimes, just knowing that a file exists isn't enough. You might also need to figure out what kind of file it is.

  • Is it a regular file you can edit?
  • A directory that holds other files?
  • Or maybe it's a symbolic link pointing somewhere else?

Depending on the type, your script might need to handle it differently.

Bash makes this easy with a few handy flags:

  • -echecks if the file exists, no matter what type, while other flags such as -f (regular file) and -d (directory) are more specific
  • -f checks if it’s a regular file (like a text or config file)
  • -d tells you if it’s a directory
  • -L checks if it’s a symbolic link

So let’s break it down with an example:

#!/bin/bash
if [ -d /path/to/your/directory ]; then
    echo "This is a directory."
elif [ -f /path/to/your/file ]; then
    echo "This is a regular file."
elif [ -L /path/to/your/link ]; then
    echo "This is a symbolic link."
else
    echo "File type unknown or does not exist."
fi

So how does this work?

Well:

  • If the path points to a directory, the script will handle it in the if block
  • If it's a regular file, the elif block takes care of it
  • And if it's a symbolic link, you get the appropriate response

This flexibility allows your script to adapt based on what kind of file it’s dealing with.

Why does this matter?

Imagine you're automating a task like backing up files. If your script mistakenly treats a directory as a regular file, things could go wrong fast.

But by checking file types ahead of time, you make sure the script behaves exactly as expected—whether it's copying files, managing directories, or handling symbolic links.

TL;DR

Adding these checks to your scripts helps prevent errors and keeps everything running smoothly, no matter what type of file you're working with.

What to do if a file doesn’t exist

Now, obviously, there will be times when your script runs and doesn’t find a file—as that’s its goal. So, what do we do in this situation?

Here’s how you can handle it:

#!/bin/bash
if [ ! -e /path/to/your/file ]; then
    echo "File does not exist. Creating file..."
    touch /path/to/your/file
else
    echo "File exists."
fi

In this example, we’re using the ! -e condition to check if the file doesn’t exist. If it’s missing, the script creates an empty file using the touch command to allow the process to keep going.

This might be fine for some cases, like when you need to create logs or temporary files. But what if the missing file is critical for the rest of the process? Should the script just continue?

For critical files—those that the rest of the script depends on—it’s often better to stop the process if the file isn’t found. Continuing without it might cause errors down the line or even corrupt the entire process.

In such cases, you might want the script to either:

  • Log an error and stop execution
  • Send an alert so you can manually intervene
  • Or perform another action to handle the situation appropriately

Let’s add an example where you stop the script if a critical file isn’t found:

#!/bin/bash
if [ ! -e /path/to/your/critical-file ]; then
    echo "Critical file not found. Exiting..."
    exit 1
else
    echo "File exists."
fi

In this case, the exit 1 command will stop the script if the critical file doesn’t exist, preventing further execution. This approach is useful when missing the file would break the process or cause major issues later on.

Additionally, permissions are something you need to check. Even if a file is missing, your script might not have the right permissions to create or access it. This can be a bigger issue for critical files. You can add a check using the -w flag to ensure the directory is writable before trying to create the file.

By planning for these scenarios - whether the file is critical or not—you ensure your scripts handle missing files in a controlled way. Whether it’s by creating the file, logging the error, or stopping the process altogether, these checks keep your automation running smoothly without unnecessary failures.

TL;DR

By planning for both non-critical and critical files, your script can handle unexpected scenarios without causing failures, making file checks crucial when integrating them into larger automation processes.

Speaking of which…

How to use file checks in automation scripts

In tasks like automated backups, managing server configurations, or running health checks, file checks prevent critical errors caused by missing files. For example, here’s how you can use a file check to automate a backup:

#!/bin/bash
backup_file="/path/to/backup/file"

if [ -e $backup_file ]; then
    echo "Backup file exists. Proceeding with backup..."
    # Add backup logic here, such as copying data to the backup file
else
    echo "Backup file not found. Creating a new backup file."
    touch $backup_file
    # Add logic to initialize the backup file, such as copying data or setting file permissions
fi

Here, the script first checks if the backup file is already in place. If it exists, the script moves forward with the backup process. You could, for example, start copying data to the file or updating it with the latest system information.

If the file doesn’t exist, the script creates a new file and initializes it. After creating the file, you might want to copy initial data, set permissions, or run other initialization tasks to ensure the backup process can continue without any issues. This prevents your automation tasks from getting derailed by a missing file.

But file checks aren’t just about backups. Imagine you're managing configuration files across multiple servers. Before rolling out updates, your script needs to confirm that those config files are present. If you skip this check, you could end up with broken configurations or inconsistent setups across your environment.

Incorporating file checks ensures that your automation tasks are resilient. For example, what happens if a critical file isn’t found? Your script might need to generate the file, log an error, or even send an alert to notify you. Adding this logic helps your script handle unexpected situations without failing.

Another thing to watch for is race conditions. If multiple scripts or processes are running simultaneously, they might try to access or modify the same file at the same time, leading to unpredictable results. To avoid this, you can use locking mechanisms or ensure file operations are atomic—meaning they either succeed completely or fail without causing partial changes.

By integrating these file checks into your automation scripts, you ensure that your processes stay reliable, flexible, and ready to handle anything thrown their way.

So what’s next?

Checking if a file exists in Bash might seem like a small task, but it can prevent critical failures and keep your automation running smoothly. Whether it’s managing backups or handling missing files, file checks ensure your scripts perform reliably and without interruption.

Now, it’s time to put this into action. Add file checks to your Bash scripts and see firsthand how much more efficient and error-free your processes become. The more you practice, the more you'll refine your automation workflows.

P.S.

Don’t forget - if you want to fast-track your Bash knowledge and get as much hands-on practice as possible, then check out my complete BASH scripting course:

learn bash

You'll learn Shell Scripting fundamentals, master the command line, and get the practice and experience you need to go from beginner to being able to get hired as a DevOps Engineer, SysAdmin, or Network Engineer!

Plus, once you join, you'll have the opportunity to ask questions in our private Discord community from me, other students, and working DevOps professionals.


I guarantee that it's is the most comprehensive and up-to-date online resource to learn Bash Scripting. Plus, we'll give you the exact steps you need to take to get hired as a SysAdmin, DevOps Engineer, or Network Engineer no matter what level of experience you have!

More from Zero To Mastery

How to Become a DevOps Engineer: Step-By-Step Guide preview
Popular
How to Become a DevOps Engineer: Step-By-Step Guide

With 400,000+ jobs available and $120,000+ / year salaries, now is the perfect time to become a DevOps Engineer! Here's your step-by-step guide (with all the resources you need to go from complete beginner to getting hired).

How To Use Bash If Statements (With Code Examples) preview
How To Use Bash If Statements (With Code Examples)

Looking to level up your Bash skills with logic? In this guide, I cover everything you need to know about if statements in Bash - with code examples!

Bash Interview Prep: 30 Essential Questions and Answers preview
Bash Interview Prep: 30 Essential Questions and Answers

Ace your Bash interview! Explore 30 key questions with code examples that cover everything from basics to advanced topics. Get interview-ready now.