Read user input from a prompt
Pause the script, show a prompt, and capture whatever the user types — for one-off prompts, simple wizards, and "please confirm" / "please enter your password" interactions.
How to read user input from a prompt in each shell
read -rp "Your name: " name`-r` preserves backslashes literally (default behavior interprets them, surprisingly). `-p PROMPT` shows the prompt on stderr. `-s` silent (passwords). `-t 10` timeout 10s. `-n 1` read 1 character (single keypress, no Enter needed).
read "?Your name: " namezsh `read` puts the prompt inside the variable spec with `?` as separator — `read "?prompt" var`. `read -s` silent. zsh `vared` provides edit-an-existing-value semantics (`vared -p "prompt: " name` pre-fills with $name).
read -P "Your name: " name`-P PROMPT` (capital P — lowercase `-p` is "show this prompt MIDline"). `-s` silent. `-t TIMEOUT` timeout. fish `read` also accepts piped stdin (handy in scripts: `echo foo | read var`).
Read-Host -Prompt "Your name"No `-Prompt` colon needed — pwsh adds `: ` automatically. `-AsSecureString` for passwords (returns `SecureString` — convert with `ConvertFrom-SecureString -AsPlainText` on pwsh 7+, or `[Net.NetworkCredential]::new("", $sec).Password` on 5.1).
set /p "name=Your name: "`set /p` reads ONE LINE into the named variable. TRUNCATES at `<TAB>` (cmd parser quirk) and on some characters. NO native silent input — Google "cmd hide password" returns ugly workarounds (`for /f` with a separate find, etc.).
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- **bash `read` without `-r` is dangerous**: by default `read` interprets backslash as a line-continuation character — so `\` followed by newline disappears, and `\anything` becomes `anything`. This corrupts paths with backslashes, regex patterns, Windows paths in scripts, etc. ALWAYS use `read -r`. Exception: when you specifically want line-continuation semantics (rare in scripts).
- **Silent input (passwords) — `read -s` echoes nothing**: useful idiom is `read -srp "Password: " PASSWORD; echo`. The trailing `echo` adds the missing newline (`-s` suppresses the newline that the user types when pressing Enter). Don't store passwords in regular variables — they remain in shell history if displayed, and may show up in `ps` listings if used as command arguments. Pass via env var (`env VAR=value cmd …`) or stdin (`cmd <<< "$PASSWORD"`) instead of arg.
- **pwsh `Read-Host -AsSecureString` returns a `SecureString` object** — pwsh-specific encrypted-in-memory type, NOT a plain string. To use it with an external program that wants a plain password: pwsh 7+ `ConvertFrom-SecureString -AsPlainText`; pwsh 5.1 `[Net.NetworkCredential]::new("", $sec).Password`. Cross-version pattern: `$plain = (New-Object PSCredential "x", $sec).GetNetworkCredential().Password`. `SecureString` is encrypted with DPAPI on Windows but stored as cleartext on Linux/macOS (where DPAPI doesn't exist) — not as protective as the name implies on non-Windows.
- **Reading with a TIMEOUT** is the right way to make an interactive script that ALSO works in CI: `read -t 10 -p "Continue? [y/N] " ans || ans=N` — if user types nothing within 10s, default to N and proceed without blocking the build. Without `-t`, the script hangs forever waiting for a terminal that doesn't exist. pwsh: there's no native timeout on `Read-Host` — wrap in a runspace: `$job = Start-Job { Read-Host "Continue?" }; if (Wait-Job $job -Timeout 10) { Receive-Job $job } else { Stop-Job $job; "no" }`. cmd: `choice /t 10 /d N /c yn /n /m "Continue?"` — `choice` is a cmd-native single-keypress prompt with built-in timeout that's actually cleaner than `set /p`.
- **Multi-line input** (paste-a-key-block-or-text): `read -d ""` (bash — change delimiter to null, read until EOF). User signals end with Ctrl-D on Unix, Ctrl-Z then Enter on Windows. For pwsh: `[Console]::In.ReadToEnd()` (read till EOF). For UI projects, `gum input --width=80 --placeholder="..."` (charmbracelet/gum) is a flexible TUI tool with built-in validation, masking, multi-line modes. Avoid building elaborate read-loops in pure shell — switch to a real TUI tool the moment the requirements exceed "one prompt, one variable".
Related commands
Related tasks
- Prompt for yes/no confirmation— Block until the user confirms a destructive action — single-keystroke Y/N, defaulting to NO, case-insensitive, with a timeout so CI never hangs.
- Escape a string for safe shell use— Quote / escape a string so it survives word-splitting, glob expansion, and interpretation as multiple arguments — the fix for "spaces in filename break my script" and shell-injection bugs.
- Enable strict mode for a shell script— Make scripts fail loudly on errors — abort on the first failed command, treat unset variables as errors, and propagate pipe failures. The opposite of "fail silently and corrupt data".
- Generate a random password— Produce a strong random password from the command line — cryptographic-quality, not `$RANDOM`.