Short answer: mkdir NAME creates a folder called NAME in the current directory, and mkdir -p path/to/folder creates the whole path in one go, without an error if part of it already exists. Add -m 750 to set the permissions at the moment the folder is created, instead of fixing them with chmod afterwards.
mkdir backups # one folder, here
mkdir -p /srv/app/releases/current # the whole path, parents included
mkdir -m 700 ~/private # created with mode 700 straight awayThe outputs on this page come from Debian 12 with GNU coreutils 9.1 and bash 5.2, run in a scratch directory; the Windows lines at the end follow Microsoft’s command reference. Ubuntu, Rocky Linux and AlmaLinux ship the same GNU mkdir; macOS and the BSDs have their own, which knows -p, -m and -v too.
mkdir cheat sheet
| Task | Command |
|---|---|
| Create one folder | mkdir logs |
| Create several folders | mkdir logs cache tmp |
| Create a nested path, parents included | mkdir -p a/b/c |
| No error if it already exists | mkdir -p logs |
| Print each folder it creates | mkdir -pv a/b/c |
| Set permissions at creation | mkdir -m 750 shared |
| Same, symbolic notation | mkdir -m u=rwx,g=rx,o= shared |
| Several subfolders at once (bash) | mkdir -p site/{public,logs,backups} |
| Folder name with spaces | mkdir "My Folder" |
| Folder name starting with a dash | mkdir -- -old |
| With owner, group and mode in one step | sudo install -d -o alice -g alice -m 755 /srv/alice |
| Create a folder and change into it | mkdir -p newproj && cd "$_" |
How do I create a folder in Linux?
mkdir takes one or more names. A name without a leading slash is relative to the directory you are in (pwd shows it); a name that starts with / is an absolute path. Several names create several folders side by side:
mkdir one two three
ls -d one two threeone
three
twoQuote a name that contains spaces. Unquoted, the shell splits it into two words and mkdir My Folder creates two folders, My and Folder. The same goes for a name that starts with a dash: mkdir -old stops with invalid option -- 'o', because mkdir reads -old as a bundle of options and has no -o. Put -- before it (mkdir -- -old) or write ./-old.
Run plain mkdir twice, or on a path whose parent is missing, and it refuses:
$ mkdir projects
$ mkdir projects
mkdir: cannot create directory ‘projects’: File exists
$ mkdir a/b/c
mkdir: cannot create directory ‘a/b/c’: No such file or directoryBoth end with exit status 1, which stops a script running under set -e. The second error is the one people hit most: plain mkdir only creates the last folder of a path, never the ones above it.
mkdir -p: parents, and no error if it exists
-p (--parents) does two things at once. It creates every missing folder along the path, and it treats a folder that already exists as success. With -v it lists what it actually created:
$ mkdir -pv a/b/c
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
$ mkdir -pv a/b/c a/b/d
mkdir: created directory 'a/b/d'The second run printed one line: a/b/c was there already, so only a/b/d was new, and the exit status was 0. That makes mkdir -p the form to use in scripts, deploy hooks and Dockerfiles, which run more than once.
-p does not paper over a file in the way. If f is a regular file, mkdir -p f still fails with File exists, and mkdir -p f/sub fails with cannot create directory ‘f’: Not a directory. Rename or remove the file first.
mkdir -m: set permissions when you create the folder
Without -m, a new folder gets mode 777 minus your umask. The usual umask is 0022, which is why folders come out as 755 (drwxr-xr-x): everyone can enter and list them, only the owner can write. The umask is set per shell, so the same command gives different results for different users and services:
| umask | New folder | Typical for |
|---|---|---|
0022 | 755 drwxr-xr-x | The common default; run umask to see yours |
0002 | 775 drwxrwxr-x | Shared group folders |
0077 | 700 drwx------ | Private data, keys, backups |
-m sets the mode explicitly and ignores the umask for that folder. It accepts the same octal and symbolic notation as chmod:
mkdir -m 700 secret # drwx------
mkdir -m u=rwx,g=rx,o= team # drwxr-x--- (750)
mkdir -m 2775 shared # drwxrwsr-x setgid: new files inherit the group
stat -c '%A %a %n' secret team shareddrwx------ 700 secret
drwxr-x--- 750 team
drwxrwsr-x 2775 sharedmkdir -m 777 really does create a world-writable folder, umask or not. That is almost never what a web server or an upload directory needs; the chmod guide explains why and what to use instead.
Several folders at once with brace expansion
Bash and zsh expand a comma list in braces into separate words before mkdir runs, so one line can build a whole tree:
mkdir -p site/{public,logs,backups}
mkdir -p app/{src,tests}/{unit,integration}
mkdir -p months/{01..12}
find site app -type d | sortapp
app/src
app/src/integration
app/src/unit
app/tests
app/tests/integration
app/tests/unit
site
site/backups
site/logs
site/public{01..12} keeps the leading zero, so the months sort correctly. Two traps:
- No spaces inside the braces.
mkdir {one, two}is two words to the shell, and mkdir creates two folders literally named{one,andtwo}. - Not every shell expands braces. Brace expansion is a bash and zsh feature, not POSIX. Debian’s
/bin/shis dash, and theremkdir {a,b}creates one folder called{a,b}. That catches scripts that start with#!/bin/shand lines in a crontab, which cron runs with/bin/sh. Write the folders out, or run the line withbash -c.
mkdir: cannot create directory: Permission denied
mkdir: cannot create directory ‘/var/www/site’: Permission deniedTo create a folder you need write and execute permission on its parent directory, plus execute permission on every directory above it. Your own home directory qualifies; /var/www, /srv, /opt and /etc belong to root. namei -l (util-linux) shows owner and mode for every step of a path, which tells you where it stops:
namei -l /var/www/sitef: /var/www/site
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root www
site - No such file or directoryHere /var/www is owned by root with 755, so only root may create anything in it. Three ways forward, best first:
- Create it once as root and hand it over:
sudo install -d -o deploy -g www-data -m 750 /var/www/site. From then on the deploy user creates everything below it without sudo. See the chown guide for choosing owner and group. - Work inside a directory you own, such as your home, if the path is up to you.
sudo mkdiron its own works, but leaves a root-owned folder that your application then cannot write to, which only moves the error.
Do not confuse this with bash: ./script.sh: Permission denied, which is about running a file, not creating one; that one is covered in bash: Permission denied.
Other mkdir errors and what they mean
| Message ends with | Meaning | Fix |
|---|---|---|
| File exists | A folder or a file of that name is already there | Use mkdir -p for folders; rename a file in the way |
| No such file or directory | A parent folder in the path is missing | mkdir -p |
| Not a directory | Part of the path is a regular file | Check the path; rename the file |
| Permission denied | No write and execute permission on the parent | See above: install -d as root, then hand it over |
| Read-only file system | The filesystem is mounted read-only, often after disk errors | Read-only file system |
| No space left on device | Disk full, or out of inodes while space is still free | No space left on device |
| File name too long | One name is over 255 bytes (ext4, XFS) | Shorten it; multibyte characters count more than once |
| invalid option | The name starts with a dash | mkdir ./-name |
Creating a folder in another user’s home directory
As an administrator, sudo mkdir /home/alice/uploads creates the folder, but it belongs to root. Alice can see it and cannot write into it. Checked with a folder owned by another user: the new subfolder came out as root:root, mode 755. Create it as the user instead, or with the right owner from the start:
# as alice herself (alice must be able to reach the parent directory)
sudo -u alice mkdir -p /home/alice/uploads
# or as root, with owner, group and mode set in one step
sudo install -d -o alice -g alice -m 755 /home/alice/uploads
# already created as root? hand it over
sudo chown -R alice:alice /home/alice/uploadssudo mkdir -p has the same problem one level up: every parent it creates is root-owned too. For a .ssh folder, owner and mode both matter, because SSH ignores keys in a folder others can write to; creating a sudo user walks through that setup.
mkdir vs install -d
install is the coreutils tool that copies files into place with a given owner and mode; with -d it creates directories instead. It is what package scripts and Makefiles use, and it fills the gaps mkdir leaves:
| mkdir -p -m MODE | install -d -m MODE | |
|---|---|---|
| Creates missing parents | Yes | Yes, always (no -p needed) |
| Mode applies to | The last folder only | The last folder only |
| Folder already exists | Left alone, mode unchanged | Mode (and owner, if given) set again |
| Owner and group | Whoever runs it | -o USER -g GROUP |
| Available on | Every Unix | GNU coreutils and the BSDs |
install -d -m 750 -o nobody -g nogroup deploy/releases/current
stat -c '%A %U:%G %n' deploy deploy/releases deploy/releases/currentdrwxr-xr-x root:root deploy
drwxr-xr-x root:root deploy/releases
drwxr-x--- nobody:nogroup deploy/releases/currentThe parents came out with the defaults, only the target got the owner and mode. The practical difference is the third row: on an existing folder with mode 755, mkdir -p -m 700 left it at 755, while install -d -m 700 set it to 700. For a provisioning script that must converge on the right state every time it runs, that is the one to use.
mkdir in scripts
Create a folder and change into it
mkdir -p ~/projects/newapp && cd "$_"
# or as a function in ~/.bashrc
mkcd() { mkdir -p -- "$1" && cd -- "$1"; }$_ holds the last argument of the previous command, here the path you just created. Quote it, in case the path contains spaces.
mkdir as a lock
Creating a directory is atomic: of two processes that try at the same moment, exactly one succeeds. That makes plain mkdir (without -p) a simple lock for a cron job that must not run twice at once:
#!/bin/bash
lock=/tmp/nightly-backup.lock
if ! mkdir "$lock" 2>/dev/null; then
echo "already running" >&2
exit 1
fi
trap 'rmdir "$lock"' EXIT
# ... the actual work ...The second call of the same mkdir fails while the first holds the folder, and the trap removes it when the script ends. If the script is killed hard (kill -9) or the server goes down mid-run, the folder stays behind and blocks every later run until you remove it. flock from util-linux does not have that problem, because the kernel drops its lock when the process dies; cron job not running shows it in a crontab line.
mkdir and md on Windows
Windows has mkdir too, and md is the same command. Per Microsoft’s command reference, cmd creates intermediate folders on its own while command extensions are enabled, which is the default, so there is no -p:
mkdir C:\data\logs\2026
md "C:\Backups\Nightly Copies"
if not exist C:\data\logs mkdir C:\data\logsUnlike mkdir -p, cmd still complains when the folder exists (A subdirectory or file … already exists), hence the if not exist guard in batch files. In PowerShell, mkdir runs New-Item -ItemType Directory, which also creates missing parents; add -Force to make it succeed when the folder is already there:
New-Item -ItemType Directory -Path C:\data\logs\2026 -ForceFolders you create on a fresh server
On a new VPS, three mkdir lines come up almost every time, each with the owner and mode it needs:
# a web root the deploy user owns and the web server can read
sudo install -d -o deploy -g www-data -m 750 /var/www/example.com
# a backup folder only root can read
sudo install -d -m 700 /root/backups
# a mount point for a separate partition or disk
sudo mkdir -p /dataA mount point is an ordinary empty folder; whatever you mount there appears in it. On a VMHeaven VPS, storage added from the panel enlarges the existing virtual disk, and you grow the system partition into it (many Linux images do that at the next reboot), so extra space needs no mount point of its own. A folder like /data only matters if you deliberately keep data on a separate partition. For everything else around folders and permissions, the Linux commands cheat sheet has the neighbouring commands on one page.
Frequently asked
How do I create a folder in Linux?
Run mkdir followed by the name, for example mkdir backups, which creates the folder in the current directory. Give an absolute path such as mkdir /srv/backups to create it somewhere else, and use mkdir -p /srv/app/releases to create any missing parent folders on the way. Quote names that contain spaces: mkdir "My Folder".
What does mkdir -p do?
It creates every missing folder along the path and treats a folder that already exists as success instead of an error, so it is safe to run more than once in scripts and deploy hooks. It still fails when a regular file of the same name is in the way.
How do I create a directory with specific permissions?
Use mkdir -m, for example mkdir -m 750 shared, which sets the mode at creation and ignores the umask. With -p the mode applies only to the last folder: the parents get the umask default, and a folder that already exists keeps its old mode. install -d -m 750 also sets the mode on an existing folder.
Why does mkdir say Permission denied?
Creating a folder needs write and execute permission on the parent directory, and folders such as /var/www, /srv, /opt and /etc belong to root. Create the folder once with sudo install -d -o USER -g GROUP -m 755 PATH so the right user owns it; a plain sudo mkdir leaves a root-owned folder the user still cannot write to.