How To Make A Directory In Linux

How To Make A Directory In Linux

Reading time1 min
#Linux#Scripting#Automation#mkdir#DirectoryCreation#LinuxCommands

Mastering Directory Creation in Linux: Beyond mkdir Basics

Consider a deployment pipeline where scripts need to provision directory trees atomically—mkdir chooses whether the operation is seamless or riddled with permission errors and race conditions.

A basic command:

mkdir mydir

creates a directory. But real-world workflows demand more. For example:

  • Ensuring nested hierarchies are ready (and idempotent)
  • Setting permission masks immediately (e.g., for secret mounts or build artifacts)
  • Handling the case where a directory may or may not already exist, without polluting logs with benign errors
  • Automating robust scaffolding across environments

Nested Directories: mkdir -p

Creating structures like output/data/model/v1 in one go is standard in CI jobs, especially with unpredictable build agents. Without the -p flag:

mkdir output/data/model/v1
# mkdir: cannot create directory ‘output/data/model/v1’: No such file or directory

With -p, parent components are created as needed.

mkdir -p output/data/model/v1

Tip: -p is idempotent—invoking the same command repeatedly does not throw an error if the directory tree already exists. This property is valuable in parallelized scripts and Jenkinsfile stages.

Permission Control on Creation: mkdir -m

Sometimes the default umask is too coarse. For example, storing SSH keys or secrets:

mkdir -m 0700 ~/.ssh_private

This preempts race conditions where a directory is briefly world-readable, plugging a security gap that can arise in automated provisioning just after user creation.

Quick check post-creation:

ls -ld ~/.ssh_private
# drwx------ 2 alice alice 4096 Jun 10 12:10 /home/alice/.ssh_private

Gotcha: The umask still interacts; -m 0777 with a restrictive umask will not result in world-writable permissions. Explicitly set, but always verify.

Avoiding "File Exists" Failures

Automations fail when scripts rerun and directories already exist:

mkdir archive
# mkdir: cannot create directory ‘archive’: File exists

The best-practice: always use mkdir -p in automation unless you require a failure for logic reasons. For noisy environments, you can suppress errors:

mkdir archive 2>/dev/null || true

But this pattern is brittle. -p is cleaner, less shell-dependent, and POSIX-compliant on modern distros (tested: Ubuntu 18.04+, CentOS 7+).

Bulk Directory Creation: Brace Expansion

Initial application scaffolding often requires multiple sibling and nested directories:

mkdir -p src/{lib,tests,it}/data

Yields:

src/
├── lib
├── tests
│   └── data
└── it
    └── data

Note: This pattern eliminates loop boilerplate in provisioning scripts—a single command can establish a multi-level hierarchy. bash and zsh both expand braces natively (Bash 4.0+ recommended).

Chained Commands

A common idiom:

mkdir -p /srv/app/config && cd /srv/app/config

This avoids race failures on first run, and skips redundant navigation if repeated. The pattern is core for idempotence in Dockerfile snippets or entrypoint scripts.

Scripting: Existence Checks and Logging

In cron or daily backup jobs, tracking directory creation status helps with debugging and incident correlation. Example:

BACKUP_DIR="/var/backups/2024-06-10"
[ -d "$BACKUP_DIR" ] || {
    mkdir -p "$BACKUP_DIR"
    echo "$(date +%F\ %T) Created $BACKUP_DIR" >> /var/log/backup-create.log
}

Non-obvious tip: Atomicity isn't guaranteed—two jobs starting simultaneously can both pass the [ -d ... ] test. For high-integrity requirements, use mkdir -p and check $?, or rely on advisory file locks (flock).

Side Note: SELinux Contexts

On hardened hosts, mkdir does not set SELinux labels; restoring default contexts may require:

restorecon -Rv /srv/app/data

Missing this step can cause "Permission denied" on subsequent file access, even with correct POSIX permissions.

Known Issue: Race Conditions

While mkdir -p is robust, scripts that combine mkdir with subsequent file creation may still race in highly parallel environments (e.g., distributed build farms). Prefer dedicated provisioning steps or guardrails when possible.


Summary

  • Use mkdir -p for all automation, to ensure idempotence and suppress "File exists" noise
  • Leverage -m to set permissions at creation time, not after
  • Employ brace expansion to build hierarchical structures rapidly
  • Check and log directory creation in scripts; anticipate races
  • For SELinux-enabled hosts, update contexts post-creation
  • Idempotence and atomicity are essential—don't rely on luck in CI/CD environments

References: