Bash read Command

Updated on

5 min read

Linux Bash read

Bash ships with a number of built-in commands that you can use on the command line or in your shell scripts.

In this article, we’ll explore the built-in read command.

The Bash read Built-in

read is a bash built-in command that reads a line from the standard input (or a specified file descriptor) and splits it into words. The first word is assigned to the first variable name provided, the second one to the second name, and so on.

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

read [options] [name...]

To see in action how the command works, open a terminal, type read var1 var2, and hit “Enter”. The command will wait for the user to enter the input. Type two words (e.g., Hello, World!) and press “Enter” again.

read var1 var2Hello, World!

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

echo $var1echo $var2
Hello,
World!

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

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

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

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

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

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

If the number of arguments (variables) supplied to the read command is bigger than the number of words read from the input, the last variable receives all remaining input:

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

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

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

Backslash Escaping and the -r Option

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

Below is an example showing how read works when invoked with and without the -r option:

read <<< "Hello, \tWorld!"printf %s "$REPLY"
Hello, tWorld!
read -r <<< "Hello, \tWorld!"printf %s "$REPLY"
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 one or more spaces, tabs, and newlines as delimiters. To use another character as a delimiter, assign it to the IFS variable (Internal Field Separator).

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

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

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 an empty value representing the segment between the delimiters. It is created because we used two delimiter characters next to each other(::).

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

You can use more than one delimiter to split the line. When specifying multiple delimiters, assign the characters to the IFS variable without a space between them.

Here is an example using _ an - as delimiters:

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

Prompting the User

When writing interactive bash scripts, you can use the read command to prompt the user for input.

To specify a prompt string, use the -p option. The prompt is printed before the read is executed and doesn’t include a newline.

Here is a simple example:

read -r -p "Are you sure?"

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

The code below will prompt the user for a system reboot :

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

If the shell script asks users to enter sensitive information, like a password, use the -s option that tells read not to print the input on the terminal (to silence echoing):

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

Assign the Words to an Array

To assign words in an array instead of variable names, invoke the read command with the -a option:

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

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

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

The Timeout Option

The read built-in command also supports a -t timeout option, which limits the wait time for input.

The timeout value is measured in seconds and can be an integer or a floating-point number (e.g., 0.5 for half a second).

If a complete line of input arrives before the timeout, read succeeds. If it times out without a full line, it fails (with an exit status greater than 128) and discards any partial input.

Here is a basic example:

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

When the timeout is set to 0, the command checks if input is immediately available and returns success (0) if it is. Otherwise, the command returns failure without waiting.

Conclusion

The read command is a versatile tool for reading and splitting input lines in Bash scripts and interactive sessions.

If you have any questions or feedback, feel free to leave a comment.