Reading User Input
Most scripts run on their own, but sometimes you need to ask the person running the script a question first. Maybe you need a username, a password, or a simple “are you sure?” before deleting something. The Bash built-in command read (a command baked into the shell that pauses and waits for someone to type) is how you collect that input. This page shows you how to read values, show prompts, hide passwords, set sensible defaults, and build a safe confirmation step before a destructive action.
What read does
read pauses your script, waits for the user to type a line and press Enter, and stores what they typed into a variable. By default it reads one line.
#!/usr/bin/env bash
echo "What is your name?"
read name
echo "Hello, $name!"
Run it:
chmod +x greet.sh
./greet.sh
Output:
What is your name?
Ada
Hello, Ada!
The word name after read is the variable name. After the user presses Enter, $name holds their answer. If you do not give read a variable name, Bash stores the line in a default variable called $REPLY.
Tip: Always quote your variables when you use them, like
"$name". If the user types nothing or types text with spaces, quoting keeps your script from breaking.
Showing a prompt with read -p
Using a separate echo line for the question works, but read has a cleaner way. The -p flag (short for “prompt”) prints a message on the same line and then waits, with the cursor sitting right after your text.
#!/usr/bin/env bash
read -p "Enter the server hostname: " hostname
echo "You entered: $hostname"
Output:
Enter the server hostname: web-01
You entered: web-01
This reads better and keeps the cursor next to the question, which is the standard look for command-line tools.
When to use this: any time you ask a single short question. Use -p instead of a separate echo so the prompt and the input stay on one line.
Hiding passwords with read -s
When you ask for a password or any secret, you do not want it showing on screen where someone could read it over your shoulder, and you do not want it saved in your terminal scrollback. The -s flag (short for “silent”) hides what the user types.
#!/usr/bin/env bash
read -s -p "Enter your database password: " db_password
echo # print a newline because -s swallows the Enter key's line break
echo "Password received (${#db_password} characters)."
Output:
Enter your database password:
Password received (16 characters).
Notice the lone echo after the silent read. Because -s hides everything including the Enter key, the cursor stays on the prompt line. A bare echo prints a blank line so your next message starts cleanly. The ${#db_password} part counts how many characters were typed without ever printing the password itself.
Security warning: Never put a password directly inside your script file, and avoid passing secrets on the command line (they show up in
psand shell history). Reading them at runtime withread -skeeps them out of files and process listings. For automation that cannot type, use a secrets manager or an environment variable loaded from a protected file (chmod 600).
Providing default values
Often a question has an obvious answer, and you want to let the user just press Enter to accept it. Bash gives you a clean pattern using parameter expansion: read into a variable, then fall back to a default if it is empty.
#!/usr/bin/env bash
read -p "Which port should the app use? [8080]: " port
port="${port:-8080}"
echo "Using port $port"
Output (user pressed Enter):
Which port should the app use? [8080]:
Using port 8080
The expression ${port:-8080} means “use $port, but if it is empty or unset, use 8080 instead.” Showing the default in square brackets in the prompt, like [8080], is a common convention so the user knows what they will get if they do nothing.
Useful read options
| Option | What it does | When to use it |
|---|---|---|
-p "text" | Shows a prompt on the same line | Almost every interactive question |
-s | Hides typed characters (silent) | Passwords, API keys, secrets |
-r | Treats backslashes literally (no escaping) | Reading file paths or any raw text — use it by default |
-t N | Times out after N seconds | Stop waiting forever in automated runs |
-n N | Returns after N characters (no Enter needed) | Single-key answers like y/n |
-a arr | Reads words into an array | Collecting a list on one line |
Tip: Get into the habit of writing
read -reverywhere. Without-r, Bash treats a backslash as an escape character, which mangles Windows paths and other text. The-rflag almost never hurts.
A safe confirmation prompt before a destructive action
The most important use of read in DevOps work is asking “are you sure?” before something dangerous, like deleting files or dropping a database. Here is a complete, safe pattern that defaults to “no” so an accidental Enter never destroys anything.
#!/usr/bin/env bash
set -euo pipefail
target="/var/log/myapp"
read -r -p "Delete all logs in $target? This cannot be undone. [y/N]: " answer
case "${answer,,}" in
y|yes)
sudo rm -rf "${target:?}"/*
echo "Logs deleted."
;;
*)
echo "Cancelled. Nothing was deleted."
exit 0
;;
esac
Output (user typed n or just pressed Enter):
Delete all logs in /var/log/myapp? This cannot be undone. [y/N]: n
Cancelled. Nothing was deleted.
A few things make this safe and worth copying:
- The prompt shows
[y/N]with a capitalN, signalling that “no” is the default. ${answer,,}lowercases the input, soY,YES, andyall match.- The
casestatement only deletes when the user clearly says yes; anything else cancels. ${target:?}aborts with an error iftargetis somehow empty, which prevents the catastrophicrm -rf /*.set -euo pipefailat the top makes the script stop on the first error.
When to use this: before any command that deletes, overwrites, restarts a production service, or changes infrastructure. When not to: in fully automated scripts that run from cron or CI, where no human is present to answer. For those, take the choice as a command-line flag instead and skip the prompt.
Best practices
- Use
read -rby default so backslashes in input are not silently eaten. - Always show prompts with
-pand include the default value in[brackets]. - Read secrets with
-sand never store passwords in the script file. - Default destructive confirmations to “no” (
[y/N]) so a stray Enter is harmless. - Validate input after reading it — check for empty strings or wrong formats before using the value.
- Quote every variable (
"$var") to handle spaces and empty answers safely. - For non-interactive automation, accept values as arguments or environment variables instead of prompting.