How to Create and Delete Directories in Bash

How to Create and Delete Directories in Bash

If you spend any real time in a Linux or macOS terminal, you’ll quickly find that managing directories is one of the first things you need to master. I still remember the first time I accidentally deleted the wrong folder because I didn’t fully understand how rm -r worked — it taught me a lesson I never forgot. In this guide, I’m going to walk through everything you need to know about creating and deleting directories in Bash, from the absolute basics to some more advanced tricks that make daily scripting a lot smoother.

Why Directory Management Matters in Bash

Directories are the backbone of any file system. Whether you’re organizing project files, setting up a deployment pipeline, or writing a backup script, you’ll be creating, checking, and removing directories constantly. Getting comfortable with the commands mkdir and rmdir (along with rm -r for more powerful deletions) is essential for anyone who wants to automate tasks in Bash.

Creating Directories with mkdir

The most basic command for creating a directory is mkdir, short for “make directory.”

mkdir my_folder

This creates a folder named my_folder in your current working directory. If you run ls right after, you’ll see it listed.

Creating Multiple Directories at Once

You’re not limited to creating one directory at a time. You can pass several names in a row:

mkdir folder1 folder2 folder3

This creates three separate directories in one command, which is a nice time-saver when setting up a project skeleton.

Creating Nested Directories with -p

One mistake beginners often make is trying to create a nested directory structure without the parent directories existing yet:

mkdir projects/2026/bash-scripts

If projects and projects/2026 don’t already exist, this command will fail with an error like:

mkdir: cannot create directory 'projects/2026/bash-scripts': No such file or directory

The fix is the -p (parents) flag:

mkdir -p projects/2026/bash-scripts

This tells mkdir to create any missing parent directories along the way, without complaining if some of them already exist. I use -p almost every time now, because it saves me from having to check whether the parent folders exist first.

Setting Permissions While Creating a Directory

You can also assign permissions directly when creating a directory using the -m flag:

mkdir -m 755 secure_folder

This creates secure_folder with read, write, and execute permissions for the owner, and read/execute for everyone else — a common setup for shared directories.

Checking If a Directory Exists Before Creating It

In scripts, it’s good practice to check whether a directory already exists before trying to create it, especially if you want to avoid overwriting anything or triggering unnecessary errors.

if [ ! -d "my_folder" ]; then
    mkdir my_folder
    echo "Directory created."
else
    echo "Directory already exists."
fi

Here, -d tests whether the given path is a directory, and ! negates the condition, so the block only runs if the directory does not exist.

Deleting Directories with rmdir

The rmdir command removes empty directories.

rmdir my_folder

If my_folder contains any files or subdirectories, this command will fail with:

rmdir: failed to remove 'my_folder': Directory not empty

This is actually a safety feature — rmdir refuses to delete anything that still has content, which protects you from accidentally wiping out files you forgot were there.

Deleting Multiple Empty Directories

Just like mkdir, you can pass multiple directory names to rmdir:

rmdir folder1 folder2 folder3

Deleting Non-Empty Directories with rm -r

When a directory has files inside it, you need a more powerful tool: rm with the recursive flag.

rm -r my_folder

This deletes the directory and everything inside it — files, subfolders, all of it. There’s no confirmation prompt by default, so this command deserves respect. I’ve seen experienced developers still get nervous typing this one out.

Forcing Deletion Without Prompts

If you want to suppress any warnings or prompts (for example, when deleting write-protected files), you can add the -f flag:

rm -rf my_folder

This is the combination most people are referring to when they joke about “rm -rf” being dangerous. It will delete the folder and its contents without asking for confirmation, even if some files are read-only. Use it carefully, and never run it with a wildcard like rm -rf /* unless you fully understand what you’re targeting.

A Safer Alternative: Interactive Deletion

If you want a bit of a safety net, use the -i flag instead of -f:

rm -ri my_folder

This asks for confirmation before deleting each file, which can be tedious for large directories but is a good habit when you’re still building confidence with the command.

How These Commands Work Internally

When you run mkdir, Bash doesn’t do the heavy lifting itself — it calls the mkdir system utility, which in turn makes a system call (mkdir()) to the kernel. The kernel updates the file system’s directory table, allocating an inode for the new directory and linking it to its parent. Similarly, rmdir calls the rmdir() system call, which only succeeds if the directory’s inode shows zero entries besides . and .. (the current and parent directory references).

rm -r works differently: it recursively walks the directory tree, calling unlink() on files and rmdir() on directories as it works its way from the deepest level back up to the top. That’s why rm -r can delete non-empty directories while plain rmdir cannot — it’s doing the emptying and the removing in one recursive pass.

Real-World Use Cases

Project scaffolding: When starting a new project, I often use a small script to lay out the standard folder structure:

#!/bin/bash
mkdir -p myproject/{src,tests,docs,config}
echo "Project structure created."

This uses brace expansion to create four subdirectories inside myproject in a single line.

Cleaning up temporary files: A cron job might clear out a temp directory nightly:

#!/bin/bash
rm -rf /tmp/myapp_cache/*
echo "Cache cleared at $(date)"

Log rotation folders: Automatically creating a dated directory for daily logs:

#!/bin/bash
LOG_DIR="/var/log/myapp/$(date +%Y-%m-%d)"
mkdir -p "$LOG_DIR"
echo "Today's log directory: $LOG_DIR"

Automation Example: Backup Script

Here’s a slightly more complete script that creates a backup directory, copies files into it, and removes backups older than seven days:

#!/bin/bash

BACKUP_ROOT="/home/user/backups"
TODAY=$(date +%Y-%m-%d)
BACKUP_DIR="$BACKUP_ROOT/$TODAY"

mkdir -p "$BACKUP_DIR"
cp -r /home/user/documents/* "$BACKUP_DIR"

find "$BACKUP_ROOT" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;

echo "Backup completed for $TODAY"

This script creates a dated backup folder, copies documents into it, then uses find combined with rm -rf to clean up anything older than seven days.

Best Practices

  • Always use -p with mkdir when creating nested paths, to avoid unnecessary errors.
  • Prefer rmdir over rm -r when you only intend to delete empty directories — it’s a built-in safety check.
  • Quote your variables in scripts, like "$BACKUP_DIR", to avoid issues with spaces or special characters in path names.
  • Test destructive commands with echo first. For example, run echo rm -rf "$dir" before removing the echo to confirm the command looks right.
  • Avoid running deletion commands as root unless absolutely necessary, since mistakes become far more costly.

Security Considerations

Deleting directories, especially with rm -rf, is one of the most common sources of catastrophic mistakes in shell scripting. A misplaced space can turn rm -rf $dir/temp into a command that deletes far more than intended if $dir is empty or unset. To protect against this:

  • Set set -u at the top of your scripts so Bash treats unset variables as errors instead of silently expanding to nothing.
  • Consider using set -euo pipefail for stricter error handling in production scripts.
  • Never grant sudo access to scripts that perform recursive deletions unless the paths are hardcoded and verified.
  • When working with user-supplied paths, validate them against a whitelist or expected pattern before passing them to rm.

Optimization Tips

  • When deleting a huge number of files, rm -rf can be slower than alternatives like find ... -delete, especially on directories with millions of entries. For example: find /path/to/dir -type f -delete followed by rmdir on the now-empty directories can be faster on some file systems.
  • Batch directory creation using brace expansion (mkdir -p project/{a,b,c}) instead of multiple separate mkdir calls, since it reduces the number of process invocations.

Troubleshooting

“Directory not empty” error: This happens when you try rmdir on a folder that still contains files. Switch to rm -r if you genuinely want to remove everything inside.

“Permission denied” error: You may not have write permissions on the parent directory. Check with ls -ld parent_folder and adjust permissions with chmod if you have the authority to do so, or use sudo cautiously.

Directory won’t delete even with rm -rf: This can happen if a file is in use by another process, or if the file system is mounted read-only. Use lsof +D /path/to/dir to check for open file handles, and mount to confirm the file system’s mount options.

Common Mistakes

  1. Forgetting the -p flag when creating nested directories.
  2. Running rm -rf with an unquoted variable that could expand unexpectedly.
  3. Assuming rmdir will delete non-empty folders — it won’t, by design.
  4. Deleting directories without a backup, especially in production environments.

FAQs

Does mkdir create parent directories by default? No. You need to add the -p flag to automatically create any missing parent directories.

What’s the difference between rmdir and rm -r? rmdir only deletes empty directories, while rm -r deletes directories along with all their contents.

Can I undo a directory deletion in Bash? Not directly. Bash doesn’t have a built-in “trash” or “undo” feature. Recovery depends on file system snapshots, backups, or specialized recovery tools — none of which are guaranteed to work.

Is rm -rf the same as formatting a drive? No, but it can feel just as destructive if pointed at the wrong path. It only removes the files and directories you specify, but the effect on those files is permanent.

Summary

Creating and deleting directories in Bash comes down to a handful of core commands: mkdir for creation, rmdir for safely removing empty folders, and rm -r (or rm -rf) for removing folders with content. The real skill lies in using these commands carefully — checking for existence first, quoting variables, and understanding exactly what a recursive delete will touch before you run it. Once these habits become second nature, directory management becomes one of the easiest parts of shell scripting rather than a source of anxiety.

References

  • GNU Coreutils Manual: https://www.gnu.org/software/coreutils/manual/coreutils.html
  • Bash Reference Manual: https://www.gnu.org/software/bash/manual/bash.html
  • mkdir(1) man page: https://man7.org/linux/man-pages/man1/mkdir.1.html
  • rm(1) man page: https://man7.org/linux/man-pages/man1/rm.1.html
Total
2
Shares

Leave a Reply

Previous Post
How to Create and Delete Files in Bash

How to Create and Delete Files in Bash

Next Post
How to List Files and Directories in Bash

How to List Files and Directories in Bash

Related Posts