Bash read Command

By 

Updated on

8 min read

Linux Bash read

The read built-in command reads a line from standard input (or a file descriptor) and splits it into words, assigning each word to a named variable. It is one of the most frequently used built-ins for writing interactive scripts and processing text input in Bash.

The general syntax of the read built-in takes the following form:

txt
read [options] [name...]

Reading Input into Variables

To see how the command works, open a terminal, type read var1 var2, and press Enter. The command waits for input. Type two words and press Enter again:

Terminal
read var1 var2
Hello, World!

The words are assigned to the variables passed to read as arguments. Use echo or printf to verify:

Terminal
echo $var1
echo $var2
output
Hello,
World!

Instead of typing on the terminal, you can pass input to read using piping, here-string, or heredoc :

Terminal
echo "Hello, World!" | (read var1 var2; echo -e "$var1 \n$var2")
Info
read and echo are enclosed in parentheses and executed in the same subshell.
output
Hello,
World!

Here is an example using a here-string and printf:

Terminal
read -r var1 var2 <<< "Hello, World!"
printf "var1: %s \nvar2: %s\n" "$var1" "$var2"
output
var1: Hello,
var2: World!

If no variable names are provided, the entire line is assigned to the REPLY variable:

Terminal
echo "Hello, world!" | (read; echo "$REPLY")
output
Hello, World!

If the number of variables supplied to read is less than the number of words, the last variable receives all remaining input:

Terminal
echo "Linux is awesome." | (read var1 var2; echo -e "Var1: $var1 \nVar2: $var2")
output
Var1: Linux
Var2: is awesome.

When more variables are provided than words, extra variables are set to empty:

Terminal
echo "Hello, World!" | (read var1 var2 var3; echo -e "Var1: $var1 \nVar2: $var2 \nVar3: $var3")
output
Var1: Hello,
Var2: World!
Var3:

Backslash Escaping and the -r Option

By default, read interprets the backslash as an escape character, which can cause unexpected behavior. To disable backslash escaping, invoke the command with the -r option.

The example below shows how read works with and without -r:

Terminal
read <<< "Hello, \tWorld!"
printf %s "$REPLY"
output
Hello, tWorld!
Terminal
read -r <<< "Hello, \tWorld!"
printf %s "$REPLY"
output
Hello, \tWorld!

Always prefer read -r unless you specifically need escape processing.

Changing the Delimiter (IFS)

The default behavior of read is to split the line into words using spaces, tabs, and newlines as delimiters. To use a different character, assign it to the IFS variable (Internal Field Separator):

Terminal
echo "Linux:is:awesome." | (IFS=":" read -r var1 var2 var3; echo -e "$var1 \n$var2 \n$var3")
output
Linux
is
awesome.

When IFS is set to a character other than space or tab, words are separated by exactly one occurrence of that character:

Terminal
echo "Linux::is:awesome." | \
  (IFS=":" read -r var1 var2 var3 var4; echo -e "Var1: $var1 \nVar2: $var2 \nVar3: $var3 \nVar4: $var4")

The line is separated into four words. The second word is empty, representing the segment between the two consecutive : delimiters:

output
Var1: Linux
Var2:
Var3: is
Var4: awesome.

You can specify multiple delimiters by assigning more than one character to IFS with no spaces between them:

Terminal
echo 'Linux_is-awesome.' | (IFS="-_" read -r var1 var2 var3; echo -e "$var1 \n$var2 \n$var3")
output
Linux
is
awesome.

Prompting the User

When writing interactive Bash scripts, use the -p option to display a prompt before reading. The prompt is printed before read executes and does not include a newline:

Terminal
read -r -p "Are you sure? "

Generally, you would use read within a while loop to prompt the user for one of the expected answers.

The following script prompts the user for a system reboot :

sh
while true; do
    read -r -p "Do you wish to reboot the system? (Y/N): " answer
    case $answer in
        [Yy]* ) reboot; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer Y or N.";;
    esac
done

To read sensitive information such as a password, use the -s option to suppress terminal echoing:

sh
read -r -s -p "Enter your password: "

Reading a File Line by Line

One of the most common uses of read is processing a file line by line. The standard pattern is:

Terminal
while IFS= read -r line; do
    echo "$line"
done < filename.txt
  • IFS= — clears the field separator for this command so that leading and trailing whitespace in each line is preserved.
  • -r — disables backslash interpretation so that backslashes in the file are read literally.
  • < filename.txt — redirects the file as standard input to the loop.

To process the output of a command instead of a file, use process substitution:

Terminal
while IFS= read -r line; do
    echo "Found: $line"
done < <(find /var/log -name "*.log")
Warning
Avoid piping directly into a while read loop (command | while read). In Bash, the right side of a pipe runs in a subshell, so any variables set inside the loop will not be available after the loop ends. Use process substitution or input redirection instead.

Assign the Words to an Array

To read words into an array instead of individual variables, use the -a option:

sh
read -r -a MY_ARR <<< "Linux is awesome."

for i in "${MY_ARR[@]}"; do
  echo "$i"
done
output
Linux
is
awesome.

When both an array and a variable name are given, all words are assigned to the array.

Reading a Fixed Number of Characters

The -n option tells read to return after reading exactly N characters instead of waiting for a newline:

Terminal
read -r -n 1 -p "Press any key to continue..."

This is useful for “press any key” prompts and single-character menu selections. The command returns as soon as the character is received without requiring the user to press Enter.

Custom Line Delimiter with -d

By default, read stops at a newline. The -d option changes the delimiter to any character:

Terminal
read -r -d ":" var <<< "hello:world"
echo "$var"
output
hello

read consumed input up to and including the first : and assigned the preceding text to var. This is useful for parsing delimited streams or null-terminated input (-d '').

The Timeout Option

The -t option limits how long read waits for input, in seconds. Fractional values are supported (for example, 0.5 for half a second):

sh
read -r -t 10 -p "Enter your nickname (10 seconds timeout): " nickname
if [[ $? -gt 128 ]]; then
    echo "Timeout occurred!"
    nickname="(default)"
else
    echo "Hello, $nickname!"
fi

If a complete line arrives before the timeout, read succeeds. If it times out, it returns an exit status greater than 128 and discards any partial input.

When the timeout is set to 0, read checks whether input is immediately available and returns without waiting.

Quick Reference

OptionDescription
read varRead a line into var
read var1 var2Split input into multiple variables
read -r varDisable backslash escaping (recommended)
read -p "prompt" varDisplay a prompt before reading
read -s varSilent mode — do not echo input
read -t N varTimeout after N seconds
read -n N varRead exactly N characters
read -d ":" varRead until delimiter character
read -a arrRead words into an array
IFS=":" read -r a bSplit on a custom delimiter
while IFS= read -r lineRead a file line by line

For a printable quick reference, see the Bash cheatsheet .

Troubleshooting

Variables are empty after the while read loop
This happens when read runs in a subshell — most commonly when piping into the loop: command | while read. Variables set inside a subshell are not visible in the parent shell. Use process substitution or input redirection instead: while IFS= read -r line; do ...; done < <(command) or done < file.

Leading and trailing whitespace is stripped from input
By default, IFS includes space and tab, so read trims whitespace from the start and end of each word. To preserve whitespace, clear IFS before read: IFS= read -r line.

Backslash characters disappear
Without -r, read processes backslashes as escape characters (\n becomes a newline, \t becomes a tab, etc.). Always use read -r unless you specifically want this behavior.

-t option not working
The timeout option is a Bash-specific feature. If your script runs under sh (e.g., #!/bin/sh), -t may not be available. Use #!/bin/bash in the shebang line.

FAQ

Why is my variable empty after the while read loop?
The right side of a pipe runs in a subshell in Bash. Variables set inside the subshell are lost when it exits. Replace command | while IFS= read -r line with while IFS= read -r line; do ...; done < <(command) to keep variables in the current shell.

What does IFS= (empty assignment) do before read?
Setting IFS to an empty value before read disables field splitting entirely, which means leading and trailing whitespace is preserved and no splitting on spaces or tabs occurs. It is the recommended form when reading file lines: while IFS= read -r line.

Should I always use read -r?
Yes, in almost all cases. Without -r, backslashes in the input are interpreted as escape sequences, which can silently corrupt data. Use read -r by default and omit it only when you explicitly need escape processing.

How do I read input without showing it on the terminal?
Use the -s (silent) flag: read -r -s -p "Password: " pass. The input is captured in $pass without being echoed to the terminal. Remember to print a newline after (echo) since -s suppresses it.

What is the REPLY variable?
When read is called without any variable names, the entire input line is stored in the built-in variable REPLY. It is automatically available without being declared: read -r; echo "$REPLY".

Conclusion

The read command is the primary way to accept input in Bash scripts — whether prompting a user, processing a file line by line, or splitting delimited data. Use read -r by default, clear IFS when whitespace matters, and prefer input redirection over pipes to avoid subshell variable scoping issues.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page