mkdir Command in Linux (With Examples)

The mkdir command creates directories from the command line, handling everything from single folders to complex nested structures with a single command. Whether you’re organizing project files, setting up server directory trees, or scripting automated deployments, mkdir gives you precise control over directory creation and permissions without touching a file manager.

You’ll learn how to create single and multiple directories, build nested directory structures with parent directories in one step, set specific permissions during creation, handle spaces in directory names, and integrate mkdir into scripts using features like brace expansion. By understanding mkdir’s core options and practical patterns, you can structure file systems efficiently and automate directory setup tasks.

Understand the mkdir Command

If you’re new to mkdir, think of it as the foundation for organizing your Linux filesystem. It creates the folders that hold your files, scripts, logs, and configuration data. Every directory you see was created either manually with mkdir or programmatically by software that calls the same underlying system function.

Basic Syntax Breakdown

The mkdir command follows this structure:

mkdir [OPTIONS] DIRECTORY_NAME...
  • mkdir: The command itself, short for “make directory”.
  • [OPTIONS]: Optional flags that modify behavior (permissions, parent creation, verbose output).
  • DIRECTORY_NAME: One or more directory names to create. Separate multiple names with spaces.

At its simplest, mkdir project creates a directory named project in your current location. You can create multiple directories at once by listing them: mkdir docs src tests creates three separate directories.

Common Options Reference

The most useful mkdir options organized by task:

TaskOptionWhat It Does
Create parent directories-p, --parentsCreates missing parent directories automatically; does not error if directory exists
Set permissions at creation-m MODE, --mode=MODESets permissions using octal (755) or symbolic (u=rwx,g=rx,o=rx) notation
See what mkdir is doing-v, --verbosePrints a message for each directory created
Get help--helpDisplays usage information and all available options
Check version--versionShows mkdir version (GNU coreutils); not available on BusyBox systems

The -p option is particularly powerful. It handles nested directory creation without requiring you to create each level manually, and it prevents errors when a directory already exists, making it ideal for scripts that need to ensure a directory structure without failing on re-runs.

Installation

The mkdir command ships as part of GNU coreutils on virtually every Linux distribution. Verify its presence with:

mkdir --version
mkdir (GNU coreutils) 9.4
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

On Alpine Linux and other BusyBox-based systems, mkdir --version is not available. BusyBox provides a minimal mkdir that supports -p and -m flags but lacks --version and --help. Run mkdir with no arguments to see basic usage, or check busybox --help mkdir for the help text.

If mkdir is somehow missing (extremely rare, usually only in minimal containers), install the coreutils package:

Ubuntu and Debian-based Distributions

sudo apt install coreutils

Fedora, RHEL, Rocky Linux, and AlmaLinux

sudo dnf install coreutils

Arch Linux and Manjaro

sudo pacman -S coreutils

openSUSE

sudo zypper install coreutils

Alpine Linux

sudo apk add coreutils

Gentoo

sudo emerge sys-apps/coreutils

Void Linux

sudo xbps-install -S coreutils

Practical Examples

Example 1: Create a Single Directory

The most common use case is creating a single directory in your current location:

mkdir new_directory

This creates new_directory in your current working directory. The directory appears immediately with no confirmation message unless you add the -v flag.

Default permissions depend on your umask setting. With the common umask of 022, new directories get 755 permissions (owner can read/write/execute; group and others can read/execute only). Check your current umask with the umask command if you need to understand why directories appear with specific permissions.

Example 2: Create Multiple Directories at Once

When setting up project structures, you often need several directories created simultaneously:

mkdir docs src tests config

This creates four separate directories (docs, src, tests, and config) in the current location with a single command. Each directory is independent; if one already exists, mkdir will error on that specific name but still create the others.

Example 3: Create Nested Directory Structures

The -p option creates parent directories automatically, letting you build entire directory trees in one command:

mkdir -p project/src/components/auth

This creates the entire path. If project, src, components, or auth directories don’t exist, mkdir creates them all in sequence. Without -p, you’d get an error if any parent directory is missing. This option is essential for scripts that need to ensure directory structures exist without failing on re-runs.

Example 4: Set Permissions During Creation

The -m option lets you specify permissions at creation time, which is more secure than creating a directory with default permissions and then changing them with chmod:

mkdir -m 700 private_data

This creates private_data with permissions set to 700 (read, write, and execute for the owner only; no access for group or others). Verify the permissions with ls -la:

ls -la private_data
drwx------   2 user user 4096 Feb  4 10:30 private_data

Using octal notation like 700 or 755 is the most common approach, though you can also use symbolic notation: mkdir -m u=rwx,g=,o= private_data achieves the same result.

Example 5: Use Verbose Output for Confirmation

When creating many directories or running mkdir in scripts, the -v flag provides confirmation of what was created:

mkdir -v reports logs backups
mkdir: created directory 'reports'
mkdir: created directory 'logs'
mkdir: created directory 'backups'

Combine -v with -p to see the entire path creation:

mkdir -pv data/2024/november
mkdir: created directory 'data'
mkdir: created directory 'data/2024'
mkdir: created directory 'data/2024/november'

This verbose output is particularly useful in scripts where you want to log which directories were created, or when debugging to confirm mkdir is taking the expected actions.

Example 6: Handle Directory Names with Spaces

When directory names contain spaces, enclose them in quotes to prevent the shell from treating each word as a separate directory name:

mkdir "Client Projects" "Meeting Notes"

This creates two directories with spaces in their names. You can also escape individual spaces with backslashes (mkdir Client\ Projects), but quotes are clearer when directory names contain multiple spaces.

Example 7: Create Directories with Full Paths

Specify absolute or relative paths to create directories anywhere in the filesystem, not just your current location:

sudo mkdir /var/www/mysite/uploads
mkdir ~/documents/2024/invoices

The first command creates uploads in /var/www/mysite (the parent directories must already exist unless you add -p) and requires sudo because /var is a system directory. The second creates invoices in your home directory under documents/2024. Using full paths is helpful when working from different directories or when scripting directory creation for system-wide locations.

Example 8: Create Hidden Directories

In Linux, files and directories starting with a dot (.) are hidden from normal directory listings:

mkdir .cache .config .local

This creates three hidden directories. They won’t appear in ls output unless you use ls -a (show all files). Hidden directories are commonly used for application configuration, cache data, and user-specific settings that shouldn’t clutter normal directory listings.

Example 9: Use Brace Expansion for Sequential Directories

Bash’s brace expansion feature lets you generate sequences of directory names efficiently:

mkdir week{1..12}
mkdir -p project/{src,tests,docs,config}

The first command creates week1, week2, through week12. The second creates four directories under project in one command. You can combine ranges and lists: mkdir -p 2024/{q1,q2,q3,q4}/{reports,data} creates a two-level structure with quarters and subdirectories for each quarter.

Example 10: Prevent Errors When Directories Exist

The -p option silently succeeds even when directories already exist, making it perfect for idempotent scripts that can run repeatedly without errors:

mkdir -p logs backups data

Run this multiple times and it completes successfully each time. If the directories exist, nothing changes; if they’re missing, they’re created. Without -p, running mkdir logs when logs already exists produces an error and fails.

Example 11: Create Directories from a Text File

When you have a list of directories to create (perhaps from a project template or inventory), read the file with a simple loop so each name stays intact:

while IFS= read -r dir; do
  mkdir -- "$dir"
done < directory_list.txt

If directory_list.txt contains directory names (one per line), this loop creates all of them while preserving spaces and special characters. The IFS= (Internal Field Separator) prevents the shell from splitting on spaces within directory names, and -- signals the end of options to handle names that start with dashes.

Add -p to the mkdir invocation (mkdir -p -- "$dir") when the list includes nested paths so parent directories are created automatically. This pattern is useful when provisioning consistent directory structures across multiple systems or creating directories from configuration files.

Example 12: Combine Options for Complex Directory Creation

Real-world scenarios often require combining multiple mkdir options:

sudo mkdir -pvm 750 /var/app/data/{uploads,exports,cache}

This creates three directories under /var/app/data (creating /var/app/data if needed), sets permissions to 750 (owner full access, group read/execute, others none), and prints verbose output showing each directory created. Combining -p, -v, and -m gives you safe nested creation with custom permissions and confirmation feedback, while sudo provides the root permissions required in /var.

Example 13: Set Sticky Bit for Shared Directories

The sticky bit (octal 1000) protects files in shared directories so only the file owner (or root) can delete or rename their own files:

mkdir -m 1777 /tmp/shared_workspace

This creates a directory with full permissions for everyone (777) plus the sticky bit (1), resulting in octal 1777. The sticky bit is essential for directories like /tmp where multiple users need write access but shouldn’t be able to delete each other’s files. Verify the permissions:

ls -ld /tmp/shared_workspace
drwxrwxrwt 2 root root 4096 Feb  4 10:45 /tmp/shared_workspace

The t at the end of the permission string indicates the sticky bit is set.

Example 14: Set SGID Bit for Group Collaboration

The SGID (Set Group ID) bit ensures files created within a directory inherit the directory’s group ownership rather than the creating user’s primary group, which is valuable for team collaboration:

sudo mkdir -m 2775 /opt/team_project

This creates a directory with read/write/execute for owner and group, read/execute for others (775), plus the SGID bit (2), resulting in octal 2775. When team members create files in this directory, those files automatically belong to the directory’s group instead of their personal group. Verify the permissions:

ls -ld /opt/team_project
drwxrwsr-x 2 root root 4096 Feb  4 10:50 /opt/team_project

The s in the group execute position indicates the SGID bit is set. The SUID bit (4) is rarely used with directories and generally reserved for executable files requiring elevated privileges. Note that sudo is necessary here because /opt is system-owned.

Example 15: Integrate mkdir with find for Bulk Operations

When you need to recreate directory structures or mirror hierarchies, combine find with mkdir to automate complex operations:

find source_project -type d -exec sh -c 'rel=${1#source_project}; mkdir -p "backup_project$rel"' _ {} \;

This finds all directories under source_project and recreates the structure directly under backup_project. The shell snippet strips the source_project/ prefix, creates backup_project once when the root entry is processed, then appends each relative path for nested directories. This pattern is useful when preparing staging environments, creating backup directory trees before file syncs, or provisioning parallel test structures. For simpler mirroring without files, run:

rsync -av --include='*/' --exclude='*' source/ destination/

The rsync command copies only directories while skipping files, producing a clean skeleton of the original project.

Common Mistakes and Troubleshooting

Permission Denied Errors

mkdir: cannot create directory '/var/app/logs': Permission denied

This error means you lack write permission in the parent directory. Check permissions with ls -ld /path/to/parent and either request appropriate access or use a location where you have write permissions. System directories like /usr, /opt, or /var typically require sudo:

sudo mkdir /var/app/logs

File Exists Errors

mkdir: cannot create directory 'project': File exists

This error means a file or directory with that name already exists. If you want to proceed regardless (and the existing entry is already a directory), add -p to make the command idempotent. If a regular file (not a directory) blocks the path, you must remove or rename it before creating the directory.

Missing Parent Directory Errors

mkdir: cannot create directory 'projects/2024/q1': No such file or directory

Without -p, mkdir fails if parent directories don’t exist. The solution is to add -p to create the entire path at once:

mkdir -p projects/2024/q1

Always use mkdir -p for nested structures or when you’re unsure whether parent directories exist.

Special Characters in Directory Names

Avoid special characters like / \ : * ? " < > | in directory names. The forward slash is a path separator and cannot appear in names. Other characters cause shell interpretation issues. When names contain spaces, apostrophes, or quotes, always enclose the entire name in double quotes or escape special characters with backslashes.

Incorrect Permission Syntax

When using -m, ensure octal values are valid (0-7 for each digit). Common mistakes include using 8 or 9 (invalid octal digits) or forgetting that permissions require three or four digits. If symbolic notation seems clearer, use -m u=rwx,g=rx,o= syntax instead of octal.

Filesystem Limitations

Some filesystems impose path length limits (typically 4096 characters on modern Linux) or directory depth restrictions. Extremely deep nesting can cause failures. Additionally, filesystems have inode limits; if you’ve exhausted available inodes, mkdir will fail even with free disk space. Check with df -i to see inode usage.

Frequently Asked Questions

What is the difference between mkdir and mkdir -p?

The standard mkdir command creates a single directory and fails if parent directories don’t exist or if the target already exists. The -p flag changes this behavior in two ways: it creates missing parent directories automatically (so mkdir -p a/b/c creates all three levels at once), and it silently succeeds if the directory already exists instead of returning an error. This makes mkdir -p ideal for scripts where you need to ensure a directory structure exists without checking first.

How do I create a directory and change into it with one command?

Bash does not have a built-in single command for this, but you can chain mkdir and cd: mkdir newproject && cd newproject. The && ensures cd only runs if mkdir succeeds. For frequent use, add a function to your ~/.bashrc: mkcd() { mkdir -p "$1" && cd "$1"; } — then run mkcd newproject to create and enter the directory in one step.

How do I check if a directory exists before creating it in a bash script?

Use the -d test operator: [ -d "/path/to/dir" ] returns true if the directory exists. For conditional creation: [ -d "mydir" ] || mkdir mydir creates the directory only if it doesn’t exist. However, mkdir -p already handles this case—it creates the directory if missing and does nothing if it exists. For most scripts, mkdir -p is simpler than explicit existence checks.

Why does mkdir create directories with different permissions than I specified with -m?

When using mkdir -p with the -m flag, only the final (leaf) directory gets the specified permissions. Parent directories created along the path receive permissions based on your umask, not the -m value. For example, mkdir -pm 700 a/b/c creates directory ‘c’ with 700 permissions, but directories ‘a’ and ‘b’ get permissions derived from your umask (typically 755). To set permissions on all directories, create the structure first with mkdir -p, then use chmod -R to apply permissions to the entire tree.

Conclusion

The mkdir command handles everything from single folders to complex nested structures. Master -p for automatic parent creation, -m for setting permissions at creation time, and -v for confirmation feedback. These three options cover most directory creation scenarios, from organizing project files to automating server provisioning. To remove empty directories, use the rmdir command.

Leave a Comment

Let us know you are human: