Skip to content
shellmap

read-hostPrompt and read user input in PowerShell across all 5 shells

Equivalents in every shell

Bashunix
read -p "Enter name: " name

bash 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.

Zshunix
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.

Fishunix
read -P "Enter name: " name

fish 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.

PowerShellwindows
$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`).

cmd.exewindows
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

Bash
read -p "Enter name: " name
PowerShell
$name = Read-Host -Prompt "Enter name"
cmd.exe
set /p name=Enter name: 

Read a password silently (don't echo what the user types)

Bash
read -sp "Password: " pw; echo
PowerShell
$pw = Read-Host -Prompt "Password" -AsSecureString
cmd.exe
# Cmd has no silent input — shell out: for /f %i in ('powershell -c "Read-Host -AsSecureString | ConvertFrom-SecureString"') do set pw=%i

Read with a timeout (5 seconds, default to empty)

Bash
read -t 5 -p "(5s) Continue? " choice || choice=""
PowerShell
# 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.

WSL & PowerShell Core notes

pwsh`Read-Host` is identical on every pwsh platform. `-MaskInput` is pwsh 7.1+; `-AsSecureString` works on all versions but the underlying `[SecureString]` is MUCH less protective on Linux/macOS (no DPAPI — falls back to a in-memory XOR). For truly sensitive secrets on Linux/macOS, prefer environment variables or secret-manager APIs (`gpg-agent`, `keychain`, `secret-tool`) over SecureString.
WSLWSL bash `read -sp` works as expected. Cross-shell secrets: `read -sp "pw: " pw` in bash + export `WSLENV=pw/u` lets the var flow to Windows pwsh via `pwsh.exe -c '$env:pw'`. Avoid passing secrets through command-line arguments — they're visible in `ps auxf` / Task Manager during the invocation.

Common tasks using read-host

Related commands