Skip to content
shellmap

mktempCreate a unique temp file or directory without TOCTOU races across all 5 shells

Equivalents in every shell

Bashunix
mktemp

Creates a file under `$TMPDIR` (or `/tmp`) with a random name like `tmp.AbCdEf1234`. The file is created with `0600` permissions (only owner can read/write) — safe for secrets. Add `-d` for a directory instead.

Zshunix
mktemp

Same external `mktemp` binary. Zsh `=(cmd)` process substitution writes to a temp file automatically and cleans up on shell exit — useful in pipelines without needing explicit `mktemp` + `rm` bookkeeping.

Fishunix
mktemp

Same external binary. Fish ships no native temp-file helper — use `mktemp` and clean up via `function fish_exit; rm -f $tmpfile; end` or `trap`-like patterns.

PowerShellwindows
New-TemporaryFile

Returns a `FileInfo` for a `tmp<HEX>.tmp` file under `$env:TEMP`. Permissions are NTFS default (Users group readable on shared machines!). For a directory: `$d = New-Item -ItemType Directory -Path (Join-Path $env:TEMP ([Guid]::NewGuid()))`. Note `[System.IO.Path]::GetTempFileName()` exists but exposes a predictable-suffix security issue (TOCTOU window).

cmd.exewindows
set TMPFILE=%TEMP%\tmp_%RANDOM%_%TIME:~6,2%%TIME:~9,2%.tmp & type nul > "%TMPFILE%"

No native `mktemp`. `%RANDOM%` is a 5-digit pseudorandom int (~32K range) — race-prone if two scripts run in the same second. For a hardened version: call `powershell -Command "(New-TemporaryFile).FullName"` and capture stdout.

Worked examples

Create a temp directory and clean up on script exit

Bash
tmpdir=$(mktemp -d) && trap "rm -rf \"$tmpdir\"" EXIT
Fish
set tmpdir (mktemp -d); function on_exit --on-event fish_exit; rm -rf $tmpdir; end
PowerShell
$tmpdir = New-Item -ItemType Directory (Join-Path $env:TEMP ([Guid]::NewGuid())); try { ... } finally { Remove-Item $tmpdir -Recurse -Force }
cmd.exe
set TMPDIR=%TEMP%\%RANDOM%-%RANDOM% & mkdir "%TMPDIR%" & ... & rmdir /s /q "%TMPDIR%"

Custom template (e.g. project-specific prefix)

Bash
mktemp /tmp/myapp.XXXXXXXX
Fish
mktemp /tmp/myapp.XXXXXXXX
PowerShell
$f = Join-Path $env:TEMP "myapp.$([Guid]::NewGuid().ToString("N").Substring(0,8))"; New-Item -ItemType File -Path $f
cmd.exe
set TMPFILE=%TEMP%\myapp_%RANDOM%%RANDOM%.tmp & type nul > "%TMPFILE%"

Temp file in a specific directory (not `$TMPDIR`)

Bash
mktemp -p /var/cache/myapp
PowerShell
New-Item -ItemType File -Path (Join-Path "/var/cache/myapp" ([Guid]::NewGuid().ToString("N").Substring(0,8) + ".tmp"))

Gotchas

  • BusyBox `mktemp` (Alpine images, embedded Linux) drops several GNU-coreutils flags: no `-p` (use `--tmpdir`), no `--suffix`, weaker template enforcement. Dockerfiles built on `alpine` will silently behave differently from `debian-slim` — pin the image OR test on both.
  • macOS BSD `mktemp` REQUIRES a template (`mktemp /tmp/foo.XXXXXX`) on older versions — bare `mktemp` errors. GNU `mktemp` accepts bare invocation. Cross-OS scripts should always pass a template explicitly: `mktemp /tmp/$(basename "$0").XXXXXX`.
  • pwsh `[System.IO.Path]::GetTempFileName()` returns a file but with a PREDICTABLE suffix pattern (`tmp????.tmp` with 4 hex chars — 64K namespace). On multi-user Windows machines or shared CI runners, that's a TOCTOU race window. Prefer `New-TemporaryFile` (uses `Path.GetRandomFileName` → 8 random base32 chars, 40 bits of entropy).
  • cmd `%RANDOM%` produces values 0–32767 — collision likely under any concurrent workload. `%RANDOM%%RANDOM%` (two concatenated) gets to ~1 billion possible names but is still pseudo-random based on system time. For real security, shell out to pwsh `[Guid]::NewGuid()` or to `powershell New-TemporaryFile`.
  • `mktemp` files are created mode `0600` on POSIX — readable only by owner. NTFS-created temp files (pwsh `New-TemporaryFile`) inherit the parent directory ACL: on a shared workstation, that often means the BUILTIN\Users group can read them. For pwsh temp files holding secrets, explicitly set ACL: `icacls $f /inheritance:r /grant:r "$env:USERNAME:F"`.

WSL & PowerShell Core notes

pwshpwsh 6+ ships `New-TemporaryFile` on every OS. On Linux/macOS pwsh, the file lives under `/tmp` (`$env:TMPDIR` on macOS); on Windows pwsh it's `$env:TEMP`. Permissions DIFFER though: POSIX `0600`, NTFS inherited ACL. For cross-OS secret-bearing temp files, follow `New-TemporaryFile` with `icacls` on Windows / `chmod 600` on POSIX to normalise.
WSLWSL `mktemp` is GNU coreutils, lives at `/tmp` (on the WSL filesystem). Files created there are NOT visible to native Windows tools at `%TEMP%`. If a Windows tool needs to read the temp file, place it under `/mnt/c/Users/<you>/AppData/Local/Temp` (WSL-addressable form of `%TEMP%`) but be aware DrvFs slow + permission-mapping caveats apply.

Common tasks using mktemp

Related commands