read Command in Linux with Examples

Last updated Sunday, May 10, 2026 8:49 am Joshua James 10 min read

Interactive shell scripts need a clean way to pause, collect an answer, and reuse that value in the next command. The read command in Linux handles that job in Bash by reading from standard input into one or more variables, which is why it shows up in prompts, confirmation menus, line-by-line file processing, and quick parsing tasks.

Start with the portable read variable shape, then add Bash-only options such as -p, -s, -t, -a, -n, -N, and -d when your script runs under Bash. For workflows that coordinate background jobs after collecting input, the bash wait command is the natural next tool to understand.

Several examples use Bash-specific features. Options like -p (prompt), -s (silent), -t (timeout), -a (array), -N (exact characters), and -d (delimiter) are not part of POSIX sh. If your script must run with /bin/sh, print prompts with printf and keep the read usage portable.

Understand the read Command in Linux

If you are new to read, think of it as a pause button that waits for someone to answer your script before it keeps going. The read command captures a line of input from standard input (stdin) and assigns it to one or more variables. By default, read waits for user input and stores it in a variable, making it essential for interactive scripts.

Basic Syntax

read [options] variable_name
  • read is the command that captures user input.
  • [options] allows additional behavior modifications.
  • variable_name stores the input provided by the user. If you skip the variable, read stores the input in the built-in $REPLY variable.

Verify read Is a Shell Builtin

In Bash, read is built into the shell, so there is no separate package to install or external binary to locate. Confirm that with type:

type read

Expected output:

read is a shell builtin

Common read Command Options

These options cover the patterns most Bash scripts need:

TaskOptionWhat It Does
Prompt users interactively-p "prompt"Displays custom text before read waits for input (Bash only).
Capture sensitive responses-sHides characters typed in a terminal, which helps with passwords and tokens (Bash only).
Enforce timeouts-t secondsStops waiting after the specified number of seconds and returns a nonzero status on timeout (Bash only).
Accept short answers-n charsReads up to the requested number of characters but still honors delimiters such as newline (Bash only).
Require fixed-length input-N charsReads exactly the requested number of characters unless EOF or timeout stops it first (Bash only).
Preserve literal text-rKeeps backslashes from escaping the next character (POSIX compatible).
Store multiple values-a arraySaves words into indexed Bash array elements (Bash only).
Stop on custom delimiters-d delimUses the first character of delim as the input terminator instead of newline (Bash only).

Example: Capturing a Simple User Input

The smallest prompt needs one message, one read line, and one follow-up action.

echo "What is your name?"
read -r user_name
echo "Hello, $user_name!"

When you run this script and type Alice, the output looks like this:

What is your name?
Alice
Hello, Alice!

How the Basic read Prompt Works

  • The script displays a prompt asking for the user’s name.
  • The read command captures the input and stores it in the user_name variable.
  • The script then outputs a personalized greeting.

The same pattern scales to menus, confirmations, and small setup prompts once you change the variable name and follow-up action.

Use the Default $REPLY Variable

When you use read without specifying a variable name, the command automatically stores the input in the built-in $REPLY variable:

read -r
echo "You entered: $REPLY"

REPLY works well for quick prompts where a named variable would add noise. Unset or overwrite it after use so an old answer does not leak into later logic.

Capture Multiple Inputs with the read Command

Beyond capturing single values, the read command can store multiple inputs by specifying multiple variable names. When a user provides space-separated values, read assigns each value to a corresponding variable.

Example: Reading Multiple Values

echo "Enter your first and last name:"
read -r first_name last_name
echo "First Name: $first_name"
echo "Last Name: $last_name"

How read Splits Multiple Values

  • If a user enters John Doe, read stores the first value (John) in first_name and places the second value (Doe) in last_name.
  • If the user enters more words, the last variable (last_name) captures the remaining values.

Prompting for Database Credentials

System administration scripts use read to collect user credentials or configuration details in a structured manner:

echo "Enter database credentials:"
read -r db_user db_password
echo "Connecting to database as $db_user..."

Separate variable names make the assignment obvious, but do not collect real passwords this way. Use -s or a dedicated credential prompt when the value is sensitive.

Store Input in Arrays with the read Command

When the number of input fields varies, the -a option stores each word directly in a Bash array.

Example: Reading Input into an Array

read -r -a colors -p "Enter your favorite colors: "
echo "First color: ${colors[0]}"
echo "Second color: ${colors[1]}"
echo "All colors: ${colors[@]}"

How the -a Option Builds Arrays

  • The -a option tells read to store each space-separated word as an array element.
  • -p prints a prompt so users know what data to enter before the command waits for input.
  • You can access individual elements using ${array[index]} notation.
  • Use ${array[@]} to reference all array elements at once.

Reusing Arrays for Server Checks

Arrays are useful when input contains a variable number of fields. A here string keeps read in the current shell, so the array stays populated for the loop that follows. If you pipe into the command instead, the loop runs in a subshell and discards the array once the subshell exits, so stick with a here string or input redirection when you need to reuse the data.

read -r -a directories <<< "logs reports backups"
for directory in "${directories[@]}"; do
  printf 'Preparing directory: %s\n' "$directory"
done

Example: Parsing Data with Herestrings

read -r first last <<< "John Doe"
echo "First: $first, Last: $last"

Expected output:

First: John, Last: Doe

You can pair the same idea with command substitution when the source text comes from another command:

IFS="@" read -r user host <<< "$(whoami)@$(hostname)"
echo "Current user: $user on host: $host"

By setting IFS to @ for the duration of the command, the output splits cleanly into the username and hostname fields instead of treating the entire string as one value.

Use Custom Delimiters with the read Command

By default, read splits input at whitespace such as spaces, tabs, and newline characters because the Internal Field Separator (IFS) includes those values. When dealing with structured data like CSV files or other delimited formats, you often need a different delimiter, and adjusting IFS changes how read separates text.

Example: Reading CSV Data with a Custom Delimiter

The IFS variable controls how read splits words within a line. Setting it to a comma before read tells the command to split on commas instead of whitespace:

IFS="," read -r name age city <<< "Alice,30,New York"
echo "Name: $name"
echo "Age: $age"
echo "City: $city"

Expected output:

Name: Alice
Age: 30
City: New York

Why IFS=”,” Splits CSV Fields

  • IFS="," sets the delimiter to a comma.
  • The input Alice,30,New York splits into three variables: name, age, and city.
  • -r prevents backslashes from acting as escape characters.
  • Use this only for simple delimited text, not full CSV with quoted fields.

Processing CSV Rows from a File

For simple comma-delimited files, read can process one row at a time:

while IFS="," read -r name age city; do
  echo "Processing user: $name, Age: $age, City: $city"
done < users.csv

Simple field splitting is fine for basic comma-delimited rows, but it is not a full CSV parser. Quoted commas, embedded newlines, and escaped quotes need a CSV-aware tool. For line-oriented substitutions before or after parsing, the sed command is a better fit.

Using -d for Line Delimiters

While IFS controls how words split within a line, the -d option changes what marks the end of a line. By default, read stops at a newline, but you can specify a different character:

read -r -d ";" data <<< "status=ready;pending"
echo "Read until semicolon: $data"

Expected output:

Read until semicolon: status=ready

The -d option uses only the first character of its argument, so -d "::" still stops at :. The here string keeps the command in the current shell, and the command consumes the semicolon delimiter so the stored value excludes it.

Use read -d ” for NUL-Delimited Data

In Bash, read -d '' uses a NUL byte as the delimiter. It does not mean “read an empty delimiter” or “stop at a blank line.” Use it when another command produces NUL-delimited records, such as find -print0.

IFS= read -r -d '' record < <(printf 'alpha\0beta')
printf 'Record: %s\n' "$record"

Expected output:

Record: alpha

If the input never contains a NUL byte, Bash still assigns the data it received, but read returns failure at EOF. Check the exit status when a missing delimiter should stop your script.

Read Password Input Securely with read

When handling sensitive data such as passwords or API keys, displaying user input on the terminal is not ideal. The -s option ensures that input remains hidden from view.

Example: Secure Password Input

read -r -s -p "Enter your password: " password
printf "\nPassword saved.\n"

Why -s Protects Password Input

  • -s hides the password input so the terminal never displays the characters.
  • -p prints the prompt before read waits for input.

Securely Passing Passwords to MySQL

When a script needs to pass a prompted password to a client, keep the secret out of the shell command line. One safer pattern is to write a temporary client option file, restrict the file permissions with chmod, use it once, then remove it.

read -r -s -p "Enter your MySQL password: " mysql_pass
printf "\n"
tmp_cnf=$(mktemp)
chmod 600 "$tmp_cnf"
trap 'rm -f "$tmp_cnf"' EXIT

{
  printf '[client]\n'
  printf 'user=root\n'
  printf 'password=%s\n' "$mysql_pass"
} > "$tmp_cnf"

mysql --defaults-extra-file="$tmp_cnf" -e "SHOW DATABASES;"
rm -f "$tmp_cnf"
trap - EXIT
unset mysql_pass tmp_cnf

The file exists only long enough for the client command to read it, and the trap removes it if the script exits early. Always clear the variable afterward to reduce exposure in the shell session.

Add Timeouts to the read Command

In automated or unattended environments, there are scenarios where a script should proceed if the user does not enter input within a given time. The -t option allows setting a timeout to prevent indefinite waiting.

Example: Setting a Timeout for Input

read -r -t 5 -p "Enter your choice (default is 'no action'): " choice
choice=${choice:-"no action"}
echo "You selected: $choice"

How the Timeout Logic Works

  • -t 5 sets a timeout of 5 seconds.
  • If the user provides nothing, the script assigns a default value (no action).

Using Timeouts in Unattended Scripts

Unattended scripts commonly rely on timeouts:

echo "Press any key to continue, or wait 10 seconds..."
read -r -t 10 -n 1 key || echo "Timeout reached, proceeding..."

A timeout keeps a terminal-attached script from waiting forever. In non-interactive runs where stdin is already closed, read can fail immediately instead of waiting for the full timeout.

Read Single Characters with the read Command

For simple yes/no confirmations or menu selections, reading a single character is more efficient than waiting for full-text input. The -n option limits the number of characters captured.

Example: Capturing a Single Keypress

read -r -n 1 -p "Press Y to continue: " key
printf "\nYou pressed: %s\n" "$key"

Why -n 1 Captures a Single Keypress

  • -n 1 ensures that only one character is read.
  • -p displays a message before capturing input.

Quick Confirmations Such as Reboots

Scripts that require quick confirmations can branch on a single key without running the protected action directly in the example:

read -r -n 1 -p "Reboot now? (Y/N): " confirm
printf "\n"

if [[ $confirm == [Yy] ]]; then
  echo "Confirmed. Place the reboot command here after your safety checks."
else
  echo "Reboot skipped."
fi

Keep the confirmation separate from the privileged command so you can add logging, dry-run checks, or a second guard before a disruptive action.

Reading Exactly N Characters with -N

The -N option (uppercase) reads exactly the specified number of characters, ignoring any delimiters including newlines:

read -r -N 5 -p "Enter exactly 5 characters: " code
printf "\nCode entered: %s\n" "$code"

Unlike -n, pressing Enter does not terminate the command when using -N. The command waits until you enter exactly five characters, which fits fixed-length codes, PINs, or formatted input checks.

Handle read Command Return Codes

The read command returns zero when it successfully reads input and a nonzero status when it reaches EOF, times out, receives an invalid option, or hits another error. Check that status when the next command depends on user input being present.

Exit Status Values

  • 0: Successfully read input
  • Greater than 0: Error occurred (timeout, EOF, invalid variable name, etc.)

Example: Checking read Success

if read -r -t 5 -p "Enter your choice: " choice; then
  echo "You selected: $choice"
else
  echo "No input received or timeout occurred"
fi

Use this branch whenever a timeout, closed pipe, or missing file input should change what the script does next.

Read Files Line by Line with the read Command

Beyond interactive prompts, read often appears in loops that process files one line at a time. It works well for configuration files, logs, and simple batch data where each line is one record.

Example: Reading a File Line by Line

while IFS= read -r line; do
  echo "Processing: $line"
done < file.txt

Why IFS= read -r Preserves File Content

  • The while loop iterates over each line in file.txt.
  • IFS= read -r line captures the content of each line without trimming spaces or interpreting backslashes.

Watching Logs for Error Strings

Log-processing scripts often combine read with tail -f. The loop follows a user-owned log file continuously so new entries trigger your automation immediately:

while IFS= read -r log_entry; do
  echo "Checking log: $log_entry"
  [[ $log_entry == *"ERROR"* ]] && echo "Alert: An error was found!"
done < <(tail -f ./app.log)

Using an empty IFS value and the -r flag preserves each log entry exactly as written while process substitution keeps the loop in the current shell. Review the tail command in Linux if you need more control over live log following, or combine read with the grep command to filter specific patterns before processing each line.

Use the read Command Safely and Effectively

These habits prevent the most common read bugs in Bash scripts:

  • Use -r unless you intentionally want backslashes to escape the next character.
  • Use IFS= read -r line when reading complete file lines so leading spaces, trailing spaces, and backslashes survive.
  • Quote variables such as "$line" when you use captured input later.
  • Use here strings, process substitution, or input redirection when a variable must remain available after read runs.
  • Print a newline after read -s password prompts so the next message does not appear on the prompt line.
  • Check the exit status when using -t, -d, pipes, or files that may end before the expected input arrives.
  • Use a separate file descriptor when a loop reads from a file but still needs interactive prompts from the terminal.

Troubleshoot Common read Command Issues

Most read problems come from shell compatibility, subshells, word splitting, or missing delimiters. Start with the symptom that matches your script, then apply the smallest fix.

Illegal Option Errors in Non-Bash Shells

If a script runs with sh, dash, or another POSIX shell, Bash-only options can fail or behave differently. Errors often look like this:

read: Illegal option -s
read: Illegal option -t

The -p prompt option is another common portability trap. In Bash it prints a prompt, but POSIX read does not define it. Depending on the shell, read -p may fail with an illegal-option message or behave differently than the Bash prompt form. Portable scripts should print the prompt separately with printf and then call read.

printf 'Name: '
IFS= read -r name

When you intentionally use Bash-only options, make the script run under Bash:

#!/usr/bin/env bash

You can also check which shell is executing the current script:

printf '%s\n' "$0"
printf '%s\n' "$BASH_VERSION"

If $BASH_VERSION is empty, you are not running Bash.

Variable Empty After Piping to read

A common mistake is piping data into read and then finding the variable is empty:

# This does NOT work as expected
echo "hello" | read -r myvar
echo "Value: $myvar"
Value:

The variable is empty because the pipe creates a subshell for the read command, and the variable is discarded when the subshell exits. Use a here string or process substitution instead:

# Correct: use a here string
read -r myvar <<< "hello"
echo "Value: $myvar"
Value: hello

Unexpected Behavior with Whitespace

If leading or trailing spaces disappear from input, the default IFS value (space, tab, newline) is stripping them. Set IFS to an empty value and use the -r flag to preserve raw input:

# Without IFS=, leading spaces are stripped
read -r line <<< "   hello world   "
echo "[$line]"
[hello world]
# With IFS=, whitespace is preserved
IFS= read -r line <<< "   hello world   "
echo "[$line]"
[   hello world   ]

When you later reference the variable, always wrap it in double quotes (e.g., "$line") to prevent word splitting and preserve the exact content.

Backslashes Disappearing from Input

Without the -r flag, read interprets backslashes as escape characters:

# Without -r, backslashes are interpreted
read path <<< "C:\Users\test"
echo "$path"
C:Userstest
# With -r, backslashes are preserved
read -r path <<< "C:\Users\test"
echo "$path"
C:\Users\test

Always use -r unless you specifically need backslash interpretation.

Read in a Loop Consumes stdin

When using read inside a while loop that also reads from stdin, the loop may exit unexpectedly or consume input meant for the user. Use a different file descriptor to separate file input from user prompts:

# Read file on fd 3, keep stdin free for user input
while IFS= read -r line <&3; do
  echo "Processing: $line"
  read -r -p "Continue? (y/n): " answer
  [[ $answer != "y" ]] && break
done 3< file.txt

File descriptor 3 carries the file data, while stdin remains available for interactive prompts.

Conclusion

The read command is ready for interactive prompts, safe password entry, timeout handling, NUL-delimited input, and line-by-line file processing in Bash scripts. Pair it with IFS=, -r, and exit-status checks when input must stay exact, then use tools such as wget or curl when the next script step needs to fetch data from a URL.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: