read-host — Prompt and read user input in PowerShell across all 5 shells
Equivalents in every shell
read -p "Enter name: " namebash built-in. `-p PROMPT` writes the prompt to stderr (no newline). `-s` silent (for passwords). `-r` raw (don't interpret backslash escapes — almost always what you want). `-t SECS` timeout. Reads until newline; the value goes into the named variable.
read "name?Enter name: "zsh built-in. Different prompt syntax: `name?prompt` syntax embeds the prompt in the variable spec (no `-p` flag). `read -s name` for silent (passwords). `read -t SECS` for timeout. `read -k 1` reads exactly one character without waiting for Enter.
read -P "Enter name: " namefish built-in. `-P PROMPT` (capital P) writes the prompt. `-s` silent. `-l` makes the var local. Reads one full line by default; `-n N` for N chars. Newer fish (3.5+) also has `-c "default"` to pre-populate the input buffer.
$name = Read-Host -Prompt "Enter name"`-Prompt` text written to console (auto-adds `: `). `-AsSecureString` returns a `[SecureString]` (memory-protected, won't print on screen during typing). `-MaskInput` (pwsh 7.1+) masks input with `*` but returns a regular string (less secure than `-AsSecureString`).
set /p name=Enter name: cmd built-in. `set /p` reads a single line into the named variable. NO silent / password mode — typed input is fully visible (a security trap for password prompts in cmd scripts). Workaround: shell out to PowerShell `for /f %i in ('powershell -NoProfile -Command "Read-Host -AsSecureString | ConvertFrom-SecureString"') do set encrypted=%i`.
Worked examples
Prompt for a string and store it in a variable
read -p "Enter name: " name$name = Read-Host -Prompt "Enter name"set /p name=Enter name: Read a password silently (don't echo what the user types)
read -sp "Password: " pw; echo$pw = Read-Host -Prompt "Password" -AsSecureString# Cmd has no silent input — shell out: for /f %i in ('powershell -c "Read-Host -AsSecureString | ConvertFrom-SecureString"') do set pw=%iRead with a timeout (5 seconds, default to empty)
read -t 5 -p "(5s) Continue? " choice || choice=""# Read-Host has no native timeout — use a runspace: $rs = [PowerShell]::Create().AddScript({Read-Host}); $h = $rs.BeginInvoke(); if ($h.AsyncWaitHandle.WaitOne(5000)) { $rs.EndInvoke($h) } else { $rs.Stop() }Gotchas
- cmd `set /p` has NO silent / no-echo mode — a password prompt in pure cmd is fundamentally insecure (typed characters are visible AND remembered in cmd history). Always shell out to PowerShell `Read-Host -AsSecureString` for passwords; never `set /p pw=Password: `.
- pwsh `Read-Host -AsSecureString` returns a `[SecureString]` — useful, but to get the plaintext back for sending to an API, you need `[Net.NetworkCredential]::new("", $ss).Password` (or `ConvertFrom-SecureString -AsPlainText` on pwsh 7+). The SecureString itself is OPAQUE — it CAN'T be passed as a header value or query parameter.
- bash `read` without `-r` interprets backslash escapes — `\n` becomes newline in the input. Almost always pass `-r` for raw mode; the no-`-r` behaviour is a footgun for files with paths that contain backslashes (Windows paths fed through WSL bash).
- Timeout behaviour differs: bash `read -t 5` returns exit code > 128 on timeout (signals); pwsh `Read-Host` has NO timeout flag (must use runspaces or threads); cmd `set /p` blocks forever (no timeout). For deterministic timeout-on-no-input across shells, wrap in a runner script with `timeout` (Linux) or `Start-Process -Wait -TimeoutSec` (pwsh).
- pwsh `Read-Host -MaskInput` (pwsh 7.1+) returns a plaintext `[string]` while masking the on-screen typing — convenient but the result is NOT memory-protected. For true secret handling, prefer `-AsSecureString` even though the API is more cumbersome. Many tutorials wrongly recommend `-MaskInput` for passwords.