How do I create a directory, and any missing parent directories?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To create a directory along with any missing parent directories, use a recursive creation flag in your language or shell of choice: mkdir -p in Bash, Path.mkdir(parents=True, exist_ok=True) in Python, fs.mkdirSync(path, { recursive: true }) in Node.js, or Directory.CreateDirectory() in C#. Every modern platform provides this capability, and the critical behavior is always the same: create the full path if it does not exist, and do nothing if it already does.
This pattern appears constantly in deployment scripts, CI pipelines, test harnesses, and application startup code. Getting it right means writing idempotent filesystem operations that never crash on a second run.
Shell: mkdir -p
On Linux, macOS, and any POSIX-compatible system, mkdir -p is the standard tool.
The -p flag does two things:
- Creates every intermediate directory in the path that does not already exist.
- Suppresses the error that
mkdirwould normally raise if the target directory is already present.
Without -p, attempting to create /var/app/data/cache/thumbnails when /var/app/data does not exist produces an error:
You can also create multiple directory trees in a single command:
This uses brace expansion to create /opt/app/logs, /opt/app/config, and /opt/app/data/cache in one call.
Setting Permissions During Creation
To set specific permissions on the leaf directory as it is created, combine -p with -m:
Note that -m only applies to the final directory. Intermediate directories inherit the default permissions from the process umask.
Python: pathlib and os.makedirs
Python offers two APIs. The modern approach is pathlib.Path.mkdir:
The two keyword arguments are essential:
parents=Truecreates intermediate directories that do not exist.exist_ok=Trueprevents aFileExistsErrorif the directory is already present.
The older os.makedirs function does the same job:
Both accept an optional mode parameter for permissions:
Choosing Between pathlib and os.makedirs
| Feature | pathlib.Path.mkdir | os.makedirs |
| Available since | Python 3.4 | Python 2.0 |
| Object-oriented path handling | Yes | No |
Chainable with other Path methods | Yes | No |
exist_ok parameter | Python 3.5+ | Python 3.2+ |
| Typical use case | Modern codebases | Legacy code, quick scripts |
In new projects, pathlib is the better choice. It integrates naturally with other path operations like .resolve(), .glob(), and / operator for path joining.
Node.js: Recursive fs.mkdir
Node.js 10.12+ supports the recursive option on both synchronous and asynchronous directory creation:
When recursive is true, the call returns undefined (sync) or resolves (async) without error if the directory already exists. Without it, an EEXIST error is thrown.
For older Node.js versions that lack the recursive option, the mkdirp npm package provides equivalent functionality.
Java: Files.createDirectories
Java's java.nio.file.Files class provides createDirectories, which creates a directory and all nonexistent parent directories:
Unlike Files.createDirectory (singular), createDirectories does not throw FileAlreadyExistsException when the target exists, and it creates all missing ancestors. This is the Java equivalent of mkdir -p.
C# and .NET: Directory.CreateDirectory
In .NET, System.IO.Directory.CreateDirectory already handles the full path:
This method creates every directory in the specified path that does not already exist, and it does not throw if the directory is already present. No special flags are needed because recursive creation and idempotency are the default behavior.
Windows: PowerShell and Command Prompt
PowerShell uses New-Item with the -Force flag:
The -Force flag prevents failure when the directory already exists.
The built-in Windows mkdir command also creates intermediate directories automatically:
Unlike its Unix counterpart, Windows mkdir does not need a -p flag. It creates the full path by default.
Why Idempotence Matters
In automation, the best directory-creation commands are idempotent: running them once or a hundred times produces the same result with no errors. This is why flags like -p, exist_ok=True, and recursive: true exist.
Idempotent directory creation is critical in:
- CI/CD pipelines: Build steps run on fresh agents and need to set up directories every time.
- Container entrypoints: Docker containers often create runtime directories on startup.
- Application initialization: Server processes create log, cache, and upload directories before accepting traffic.
- Test setup: Test fixtures create temporary directory structures that may already exist from a previous run.
Without idempotency, any re-run of a setup script risks a crash at the first existing directory.
Common Pitfalls
- Forgetting the recursive flag: The most frequent mistake. Without
-p,parents=True, orrecursive: true, deep paths fail when any intermediate directory is missing. - Permission errors masked by path errors: A "no such file or directory" error sometimes means the parent exists but is not writable. Print the resolved path and check permissions separately.
- Relative path surprises: Creating
build/output/datacreates the path relative to the current working directory, which may differ between your terminal, your CI runner, and your application process. Always resolve the path first and log it. - Race conditions in concurrent code: Two processes calling
mkdiron the same path withoutexist_okorrecursivecan race. One succeeds, the other getsEEXIST. The idempotent flags eliminate this. - Manual string concatenation for paths: Building paths with
+or string formatting (e.g.,base + "/" + subdir) breaks on Windows backslashes. Usepathlibin Python,path.joinin Node.js, orPath.Combinein C#. - Assuming cross-platform consistency: Unix
mkdirwithout-pfails on existing directories. Windowsmkdirsucceeds. PowerShellNew-Itemwithout-Forcesucceeds on new directories but fails on existing ones. Always use the idempotent variant.
Summary
- Use
mkdir -pon Unix/Linux/macOS for shell scripts. - Use
Path.mkdir(parents=True, exist_ok=True)in modern Python, oros.makedirs(path, exist_ok=True)for older codebases. - Use
fs.mkdirSync(path, { recursive: true })or the async equivalent in Node.js 10.12+. - Use
Files.createDirectories(path)in Java. - Use
Directory.CreateDirectory(path)in C#/.NET, which is recursive and idempotent by default. - Use
New-Item -ItemType Directory -Forcein PowerShell. - Always prefer idempotent creation to avoid failures on re-runs, concurrent execution, and CI pipelines.

