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:
| Task | Option | What It Does |
|---|---|---|
| Create parent directories | -p, --parents | Creates missing parent directories automatically; does not error if directory exists |
| Set permissions at creation | -m MODE, --mode=MODE | Sets permissions using octal (755) or symbolic (u=rwx,g=rx,o=rx) notation |
| See what mkdir is doing | -v, --verbose | Prints a message for each directory created |
| Get help | --help | Displays usage information and all available options |
| Check version | --version | Shows 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 --versionis not available. BusyBox provides a minimalmkdirthat supports-pand-mflags but lacks--versionand--help. Runmkdirwith no arguments to see basic usage, or checkbusybox --help mkdirfor 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
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.
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.
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.
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.