Guides

mkdir command: create folders in Linux, with -p for parent folders and -m for permissions

The mkdir command creates folders in Linux: -p for nested paths, -m for permissions, brace expansion, and fixes for File exists and Permission denied.

Published ~8 min read
On this page

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.

any Linux
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 away

The 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

TaskCommand
Create one foldermkdir logs
Create several foldersmkdir logs cache tmp
Create a nested path, parents includedmkdir -p a/b/c
No error if it already existsmkdir -p logs
Print each folder it createsmkdir -pv a/b/c
Set permissions at creationmkdir -m 750 shared
Same, symbolic notationmkdir -m u=rwx,g=rx,o= shared
Several subfolders at once (bash)mkdir -p site/{public,logs,backups}
Folder name with spacesmkdir "My Folder"
Folder name starting with a dashmkdir -- -old
With owner, group and mode in one stepsudo install -d -o alice -g alice -m 755 /srv/alice
Create a folder and change into itmkdir -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:

bash
mkdir one two three
ls -d one two three
Example output
one
three
two

Quote 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:

Example output
$ 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 directory

Both 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:

Example output
$ 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:

umaskNew folderTypical for
0022755 drwxr-xr-xThe common default; run umask to see yours
0002775 drwxrwxr-xShared group folders
0077700 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:

bash
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 shared
Example output
drwx------ 700 secret
drwxr-x--- 750 team
drwxrwsr-x 2775 shared

mkdir -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:

bash
mkdir -p site/{public,logs,backups}
mkdir -p app/{src,tests}/{unit,integration}
mkdir -p months/{01..12}
find site app -type d | sort
Example output
app
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, and two}.
  • Not every shell expands braces. Brace expansion is a bash and zsh feature, not POSIX. Debian’s /bin/sh is dash, and there mkdir {a,b} creates one folder called {a,b}. That catches scripts that start with #!/bin/sh and lines in a crontab, which cron runs with /bin/sh. Write the folders out, or run the line with bash -c.

mkdir: cannot create directory: Permission denied

Example output
mkdir: cannot create directory ‘/var/www/site’: Permission denied

To 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:

any Linux
namei -l /var/www/site
Example output
f: /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 directory

Here /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 mkdir on 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 withMeaningFix
File existsA folder or a file of that name is already thereUse mkdir -p for folders; rename a file in the way
No such file or directoryA parent folder in the path is missingmkdir -p
Not a directoryPart of the path is a regular fileCheck the path; rename the file
Permission deniedNo write and execute permission on the parentSee above: install -d as root, then hand it over
Read-only file systemThe filesystem is mounted read-only, often after disk errorsRead-only file system
No space left on deviceDisk full, or out of inodes while space is still freeNo space left on device
File name too longOne name is over 255 bytes (ext4, XFS)Shorten it; multibyte characters count more than once
invalid optionThe name starts with a dashmkdir ./-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:

Debian · Ubuntu · Rocky · Alma
# 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/uploads

sudo 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 MODEinstall -d -m MODE
Creates missing parentsYesYes, always (no -p needed)
Mode applies toThe last folder onlyThe last folder only
Folder already existsLeft alone, mode unchangedMode (and owner, if given) set again
Owner and groupWhoever runs it-o USER -g GROUP
Available onEvery UnixGNU coreutils and the BSDs
bash
install -d -m 750 -o nobody -g nogroup deploy/releases/current
stat -c '%A %U:%G %n' deploy deploy/releases deploy/releases/current
Example output
drwxr-xr-x root:root deploy
drwxr-xr-x root:root deploy/releases
drwxr-x--- nobody:nogroup deploy/releases/current

The 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

bash
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:

bash
#!/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:

cmd
mkdir C:\data\logs\2026
md "C:\Backups\Nightly Copies"
if not exist C:\data\logs mkdir C:\data\logs

Unlike 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:

PowerShell
New-Item -ItemType Directory -Path C:\data\logs\2026 -Force

Folders 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:

Debian · Ubuntu
# 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 /data

A 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.

Related articles

All guides