Directory setup gets repetitive fast when projects, logs, uploads, and backups all need predictable paths. The mkdir command in Linux creates those directories from the shell, whether you need one folder, several siblings, or a nested tree that should be safe to create again later.
Start with the portable patterns first: basic directory creation, mkdir -p, permissions, quoted names, script-safe loops, and common errors. GNU Coreutils, uutils, and BusyBox all cover the core behavior, but version banners, help output, and some long options vary by implementation.
Understand the mkdir Command
mkdir means “make directory.” It creates filesystem directories in the current working directory or at a path you name. The command does not create files, copy content, or move into the new directory by itself; it only creates the directory entries.
mkdir Command Syntax
The basic syntax accepts one or more directory names:
mkdir [OPTION]... DIRECTORY...
mkdiris the command name.OPTIONchanges behavior, such as creating parents with-por setting permissions with-m.DIRECTORY...means one or more directory names or paths. Separate multiple arguments with spaces.
At its simplest, mkdir project creates a directory named project in your current location. If you pass several names, mkdir attempts them in order.
Verify mkdir Is Available
Most Linux systems already include mkdir through a core utilities package or BusyBox. Confirm that your shell can find it before troubleshooting a larger script:
command -v mkdir
/usr/bin/mkdir
A returned path confirms that mkdir is available. On GNU-based systems, mkdir --version shows the Coreutils version; on BusyBox systems, --version is not supported, and busybox mkdir --help shows the short -m and -p options. The GNU Coreutils mkdir manual documents the GNU long options and parent-directory behavior.
Use short options such as
-pand-min portable scripts. Long options like--parents,--mode, and--verboseare common on GNU-style systems but are not guaranteed in BusyBox-only environments.
Essential mkdir Options and Patterns
| Task | Command Pattern | What It Does |
|---|---|---|
| Create one directory | mkdir project | Creates project in the current directory. |
| Create several directories | mkdir docs src tests | Creates each named directory as a separate sibling. |
| Create missing parents | mkdir -p project/src/app | Creates every missing level and succeeds if the path already exists as a directory. |
| Set initial permissions | mkdir -m 700 private_data | Creates the final directory with the requested mode, still affected by implementation rules for parents and special bits. |
| Show created paths | mkdir -v reports logs | Prints a message for each directory actually created. |
| Protect names that start with a dash | mkdir -- -reports | Tells mkdir that later values are directory names, not options. |
Practical mkdir Command Examples
Create a Single Directory
Create one directory by passing its name to mkdir. A successful command prints nothing unless you request verbose output, so verify it with a directory test when you need confirmation:
mkdir project-notes
test -d project-notes && echo "directory exists"
directory exists
That pattern is useful in scripts because test -d checks for a directory specifically, not just any file with the same name.
Create Multiple Directories at Once
List several names after mkdir to create sibling directories in one pass:
mkdir docs src tests config
ls -d docs src tests config
config docs src tests
If one target already exists, mkdir reports that item and continues trying the remaining names. Use -p when the rerun should succeed without treating existing directories as errors.
Create Parent Directories with mkdir -p
The -p option creates every missing parent directory in the path. This is the safest form for nested project trees and repeatable setup scripts:
mkdir -p project/src/components/auth
find project -type d | sort
project project/src project/src/components project/src/components/auth
Without -p, the same nested command fails if any parent directory is missing. With -p, the command also succeeds when the final directory already exists, as long as it is actually a directory.
Set Permissions During mkdir Creation
Use -m when the new directory should start with a specific permission mode instead of your default umask-derived mode. The chmod command uses the same octal and symbolic permission language:
mkdir -m 700 private_data
stat -c '%A %a %n' private_data
drwx------ 700 private_data
The owner can read, write, and enter the directory; group and others have no access. Symbolic modes work too, such as mkdir -m u=rwx,g=,o= private_data.
When -p and -m are combined, the requested mode applies to the final directory named on the command line, not to every parent created along the way:
umask 022
mkdir -pm 700 reports/secure/archive
stat -c '%a %n' reports reports/secure reports/secure/archive
755 reports 755 reports/secure 700 reports/secure/archive
Set a temporary umask before mkdir -p, or run chmod afterward, when parent directories need stricter permissions too.
Show Created Directories with Verbose mkdir Output
The -v option prints each created directory. That makes logs and provisioning scripts easier to review:
mkdir -v monthly-reports app-logs db-backups
mkdir: created directory 'monthly-reports' mkdir: created directory 'app-logs' mkdir: created directory 'db-backups'
Combine -v with -p to see each missing level in a nested path:
mkdir -pv archive/2026/may
mkdir: created directory 'archive' mkdir: created directory 'archive/2026' mkdir: created directory 'archive/2026/may'
Create Directories with Spaces Safely
Quote directory names that contain spaces so the shell passes each full name as one argument:
mkdir "Client Projects" "Meeting Notes"
ls -d "Client Projects" "Meeting Notes"
Client Projects Meeting Notes
Backslashes can escape individual spaces, but quotes are clearer when a name contains more than one space or other shell-sensitive characters.
Create Directories with Absolute and Home Paths
mkdir accepts relative paths, home-directory paths, and absolute paths. Add -p when the parent path may not exist yet:
mkdir -p "$HOME/documents/2026/invoices"
sudo mkdir -p /var/www/example/uploads
The first command writes under your account. The second writes under /var, which is normally system-owned, so it uses sudo. Use sudo mkdir only for paths where your normal user lacks write access.
Create Hidden Directories
A name that starts with a dot becomes hidden from normal directory listings. This is common for application settings and user-local caches:
mkdir .cache .config .local
ls -ad .cache .config .local
.cache .config .local
Normal ls output hides these names. Use ls -a or ls -ad .name when you need to see them.
Generate Multiple Directory Names with Brace Expansion
Brace expansion belongs to the shell, not mkdir, but it pairs well with directory creation:
mkdir week{1..4}
mkdir -p project/{src,tests,docs,config}
ls -d week* project/*
project/config project/docs project/src project/tests week1 week2 week3 week4
The shell expands week{1..4} before mkdir runs, so mkdir receives week1, week2, week3, and week4 as separate arguments.
Make mkdir Ignore Existing Directories
Use -p when a script should create a directory if missing and keep going if it already exists:
mkdir -p logs
mkdir -p logs
test -d logs && echo "logs is ready"
logs is ready
This is often cleaner than checking with [ -d logs ] first. Keep the explicit check when the script needs different behavior for an existing directory, a regular file, or a missing path.
Advanced mkdir Techniques
Create Directories from a Text File
Read directory names line by line when a project template, inventory, or configuration file already lists the paths to create:
printf '%s\n' "Client Projects" "Meeting Notes" "reports/2026" > directory_list.txt
while IFS= read -r dir; do
mkdir -p -- "$dir"
done < directory_list.txt
find "Client Projects" "Meeting Notes" reports -type d | sort
Client Projects Meeting Notes reports reports/2026
IFS= keeps leading and trailing spaces from being trimmed, read -r prevents backslash interpretation, and -- protects names that start with a dash.
Create and Enter a Directory in One Step
Bash does not have a built-in single command that creates a directory and enters it. Chain mkdir with the cd command when you only need it once:
mkdir newproject && cd newproject
The && operator makes cd run only after mkdir succeeds. For repeated use, define a small shell function in your interactive shell:
mkcd() {
mkdir -p -- "$1" && cd -- "$1"
}
mkcd project-notes
basename "$PWD"
project-notes
Use mkdir Before Commands That Need a Destination
Commands such as cp do not create missing destination directories for you. Create the path first, then write into it:
printf 'summary\n' > monthly-report.txt
mkdir -p archive/reports
cp monthly-report.txt archive/reports/
test -f archive/reports/monthly-report.txt && echo "report copied"
report copied
This pattern also fits build recipes. In a Makefile, a recipe can run mkdir -p build/output before the compiler or packaging command writes files into that directory.
Compare mkdir with install -d
mkdir is the normal choice for creating directories. install -d is a related tool that creates directories for installation workflows and can set permissions, owner, and group in one command when those accounts already exist.
| Tool | Best Fit | Example |
|---|---|---|
mkdir | Daily directory creation, nested paths, script-safe checks | mkdir -p logs/cache |
install -d | Deployment scripts that need a directory plus install-style ownership or mode handling | install -d -m 750 release-cache |
For a simple directory, prefer mkdir. Reach for install -d when a packaging or deployment script already needs install-style metadata:
install -d -m 750 release-cache
stat -c '%A %a %n' release-cache
drwxr-x--- 750 release-cache
Set the Sticky Bit for Shared Directories
The sticky bit protects files in a shared directory so only the file owner, directory owner, or root can delete or rename them. It is the same idea used by /tmp:
mkdir -m 1777 shared_workspace
stat -c '%A %a %n' shared_workspace
drwxrwxrwt 1777 shared_workspace
The t at the end of the permission string shows that the sticky bit is set. Use a carefully chosen system path and group policy for real multi-user shared storage.
Set the SGID Bit After mkdir
The SGID bit makes new files and directories inherit the parent directory’s group. Some mkdir implementations handle special bits differently when -m is used, so the most portable workflow is to create the directory, then set SGID with chmod:
mkdir -m 775 team_project
chmod g+s team_project
stat -c '%A %a %n' team_project
drwxrwsr-x 2775 team_project
The s in the group execute position confirms SGID. For a system-owned collaboration directory, create the path with sudo, assign the intended group, and set SGID after the directory exists.
Mirror Directory Trees with find and mkdir
When you need a matching directory skeleton without copying files, combine find with mkdir. This example recreates directories from source_project under backup_project:
mkdir -p source_project/{src,docs,tests}
find source_project -type d -exec sh -c '
for dir do
rel=${dir#source_project}
mkdir -p -- "backup_project$rel"
done
' sh {} +
find backup_project -type d | sort
backup_project backup_project/docs backup_project/src backup_project/tests
The shell snippet strips the source prefix, then mkdir -p creates the same relative path under the backup directory. Use rsync -a --include='*/' --exclude='*' source/ destination/ when rsync is already part of your workflow and you only want the directory skeleton.
Troubleshoot Common mkdir Errors
Fix mkdir Permission Denied
A permission error means your user cannot write to the parent directory:
mkdir: cannot create directory '/var/app/logs': Permission denied
Check the parent directory owner and mode first:
stat -c '%A %U %G %n' /var/app
drwxr-xr-x root root /var/app
If the path is supposed to be system-owned, use sudo for the directory creation. If it is user-owned project storage, fix the parent ownership or choose a writable location instead:
sudo mkdir -p /var/app/logs
sudo test -d /var/app/logs && echo "directory exists"
directory exists
Fix mkdir File Exists Errors
A file-exists error means the target name is already taken:
mkdir: cannot create directory 'project': File exists
If the existing target is already a directory, use -p for an idempotent command:
mkdir -p project
test -d project && echo "project is ready"
project is ready
If project is a regular file, mkdir -p project still fails. Rename the file, choose a different directory name, or move the file after confirming you will not overwrite important data.
Fix Missing Parent Directory Errors
Without -p, mkdir fails when a parent directory is missing:
mkdir: cannot create directory 'projects/2026/q1': No such file or directory
Add -p so mkdir creates the full path:
mkdir -p projects/2026/q1
test -d projects/2026/q1 && echo "directory exists"
directory exists
Fix Names That Start with a Dash
A directory name that begins with - can be mistaken for an option:
mkdir: invalid option -- 'r'
Insert -- before the name to stop option parsing:
mkdir -- -reports
test -d ./-reports && echo "created"
created
Fix Invalid mkdir Permission Modes
Mode values can use octal digits from 0 through 7, or symbolic mode syntax. Values such as 999 are invalid:
mkdir: invalid mode '999'
Use a valid mode, then verify it:
mkdir -m 750 secure-cache
stat -c '%A %a %n' secure-cache
drwxr-x--- 750 secure-cache
Fix No Space or Inode Errors
mkdir can fail even when permissions are correct if the filesystem is out of data blocks or inodes:
mkdir: cannot create directory 'cache': No space left on device
Check both normal space and inode usage for the current filesystem:
df -h .
df -i .
After freeing space or inodes, rerun mkdir and verify the directory exists:
mkdir cache
test -d cache && echo "cache directory created"
cache directory created
Conclusion
mkdir is ready for daily directory work once you know when to use a plain name, when to add -p, and when permissions need a separate verification step. For cleanup, the rmdir command is the safer match when a directory is empty; non-empty directory removal needs a different workflow.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>