DEV Community

dpm_bush
dpm_bush

Posted on Originally published at sshflow.com

mkdir -p in Linux: Create Paths Safely in One Command

A setup script often needs to create a directory that may not exist yet—and may have several missing directories above it. Plain mkdir stops at the first missing parent. mkdir -p builds the path for you and can be run again when the target is already a directory.

mkdir -p projects/app/logs
Enter fullscreen mode Exit fullscreen mode

That single command creates each missing directory in the path. It’s useful in shell scripts, deployment steps, and local project setup, where you want to ensure a directory exists before writing files into it.

What -p changes

Without -p, mkdir creates the directory you name only if its parent already exists:

mkdir projects/app/logs
Enter fullscreen mode Exit fullscreen mode

If projects doesn’t exist, the command fails with a “No such file or directory” error. Create each level first, or use -p:

mkdir -p projects/app/logs
Enter fullscreen mode Exit fullscreen mode

The -p option means --parents. It has two practical effects:

  • Missing parent directories in the path are created.
  • If the requested directory already exists as a directory, the command succeeds without changing it.

For a closer look at the basic command and creating a single directory, see this guide to using mkdir in Linux.

Why it’s useful in scripts

A script may run more than once: during development, after a deployment retry, or as part of a recurring job. Without -p, trying to create an existing directory causes an error. With it, the same command is safe to repeat:

mkdir -p /var/log/myapp
Enter fullscreen mode Exit fullscreen mode

If /var/log/myapp already exists as a directory, mkdir -p leaves it alone. It doesn’t clear its contents, reset its permissions, or change its ownership. This makes it an easy way to express “make sure this directory exists,” but it is not a directory-reset operation.

There is one important exception: if a regular file already uses the requested name, mkdir -p still fails. A file cannot serve as a directory, so the command can’t satisfy the request.

Creating several paths

You can pass multiple paths to one mkdir invocation. Each path is handled independently:

mkdir -p project/src project/test project/docs
Enter fullscreen mode Exit fullscreen mode

In Bash and Zsh, brace expansion can shorten lists of sibling directories:

mkdir -p project/{src,test,docs}
Enter fullscreen mode Exit fullscreen mode

The shell expands that expression into separate arguments before it runs mkdir. Brace expansion is a shell feature, not part of mkdir itself, so don’t assume it works in every shell. The explicit form is easier to carry between environments.

If a path contains spaces, quote it so the shell treats it as one argument:

mkdir -p "My Project/logs"
Enter fullscreen mode Exit fullscreen mode

Without quotes, the shell splits the text at the space and mkdir receives different paths than you intended.

-p does not set permissions

The p in mkdir -p stands for parents, not permissions. To specify a mode for a directory you’re creating, mkdir has the separate -m option:

mkdir -m 750 restricted_dir
Enter fullscreen mode Exit fullscreen mode

You can combine the options:

mkdir -p -m 750 projects/app/logs
Enter fullscreen mode Exit fullscreen mode

There’s a subtle detail here: the mode supplied with -m applies to the directory named on the command line when it is created. It does not set that same mode on intermediate parent directories created along the way. For GNU mkdir, intermediate directories have their own creation behavior, including owner write and execute bits needed to continue creating the path. Exact behavior can differ between implementations, so check the target system’s mkdir manual if a script depends on precise permissions across platforms.

Also, -m doesn’t modify an existing directory when used with -p. If you need to change permissions after creation, use a permission-management command deliberately; this overview of Linux file permissions explains the relevant chmod options and risks.

Common mistakes to avoid

Expecting mkdir to create files. It creates directories only. To make an empty file inside a newly created path, run a separate command:

mkdir -p projects/app/logs
touch projects/app/logs/app.log
Enter fullscreen mode Exit fullscreen mode

Assuming -p fixes every error. It handles missing parents and an already-existing directory. It can’t turn a regular file into a directory, and it won’t override access restrictions that prevent you from creating a path.

Treating it as a cleanup or permissions command. Existing contents and permissions are left alone. Use the right separate command for any changes you actually want.

Forgetting to quote paths. Shells split unquoted arguments on spaces. Quote a path whenever it may contain spaces.

Quick comparison

Command Missing parents Existing target directory
mkdir path Fails Fails
mkdir -p path Creates them Succeeds without changing it
mkdir -m 750 path Fails Fails; mode applies when created
mkdir -p -m 750 path Creates them Succeeds without changing it; mode applies to the named directory when created

For everyday use, remember the distinction: plain mkdir creates a directory whose parent is already there; mkdir -p creates the missing path and makes an existing directory a harmless no-op. Use -m when you need to specify permissions, and don’t assume it applies the same mode to every parent created along the way.

I originally published a more detailed version of this guide on the SSHFlow blog.

I'm also building SSHFlow — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.

Top comments (0)