read Command: Interactive Input in Shell Scripts

read Command: Interactive Input in Shell Scripts

"I want my script to pause and let the user type in a name or password." When you hit that moment, the read command is the answer. In this article, Lina and Linny-senpai walk through how to capture keyboard input and read files with read, step by step.

What You'll Learn

  • What the read command does and why it matters
  • How to use prompts (-p), hidden input (-s), and timeouts (-t)
  • The classic while read pattern for processing a file line by line
  • Two beginner pitfalls: the "pipe trap" and why you should add -r

1. What Is the read Command?

Conclusion: read is a builtin that reads one line from standard input into a variable, making your script interactive.

Lina: Linny-senpai, I was writing a shell script and reached a point where I want the user to type something in. How do I do that?
Linny-senpai: That is exactly what the read command is for. read takes one line typed on the keyboard and stores it in a variable.

What read does

read is a shell builtin that reads one line from standard input (such as the keyboard) and stores it in a variable. Use it whenever you want the user to enter something and then use that value inside your script.

Lina: Is a "builtin" different from commands like ls or cat?
Linny-senpai: Good question. ls and cat are commands that exist as executable files, like /bin/ls. But read is a feature built into the shell itself. That is why which read often finds nothing. Try type read instead and you will see read is a shell builtin.

2. The Most Basic Usage

Conclusion: Type read variable and the shell waits; the line you enter before pressing Enter goes into that variable.

Lina: I want to try it right away. Show me the simplest form.
Linny-senpai: Type this. After you press Enter, the cursor stops and waits for your input.
read name
Lina: It paused. So if I type Lina here and press Enter...?
Linny-senpai: That text "Lina" goes into the variable name. Let's check what's inside.
read name
Lina
echo "Hello, $name"
Hello, Lina

Add $ to read a variable's value

The value you stored with read name is retrieved by adding a leading $, as in $name. Wrapping it in double quotes like echo "$name" is the safe style: it handles values that contain spaces correctly.

3. Showing a Prompt (-p)

Conclusion: read -p "message" variable prints a prompt before the input so the user knows what to type.

Lina: But if the cursor just stops silently, the user has no idea what to type, right?
Linny-senpai: Exactly. So we usually use the -p option to show a prompt message along with the input.
read -p "Enter your name: " name
echo "Welcome, $name"
Enter your name: Lina
Welcome, Lina
Lina: Nice! Now it's obvious what to type.
Linny-senpai: Right. The string after -p is printed as-is. Ending it with a space like : makes the input position easier to read, so I recommend it.

4. Reading Several Values at Once

Conclusion: List multiple variable names after read and space-separated input is distributed into each one.

Lina: Can I ask for a few things at once, like a first name and a last name?
Linny-senpai: Yes. List the variable names separated by spaces after read. If the input is also space-separated, each value goes to the matching variable.
read -p "First and last name: " first last
echo "First: $first / Last: $last"
First and last name: Lina Yamada
First: Lina / Last: Yamada

Extra input goes into the last variable

With read a b (two variables) but input 1 2 3 4, a gets 1 and b gets all the rest (2 3 4). If there is too little input, the leftover variables stay empty.

5. Hiding Password Input (-s)

Conclusion: read -s does not echo the typed characters, so use it for passwords and other secrets.

Lina: When the user types a password, having it visible on screen is a problem, isn't it?
Linny-senpai: That's where the -s (silent) option comes in. The characters you type are not shown on screen. Use it when reading passwords or secret values.
read -s -p "Password: " pass
echo
echo "Characters entered: ${#pass}"
Password:
Characters entered: 8
Lina: Nothing appeared while I typed, but it still captured the value.
Linny-senpai: Right. -s only hides the display; the value is safely stored in the variable. Because -s also suppresses the newline when you press Enter, adding one echo right after keeps the output tidy. ${#pass} is the syntax for the length of a variable.

6. Adding a Time Limit (-t)

Conclusion: read -t seconds makes read give up automatically if no input arrives within the given time.

Lina: If nobody types anything, the script just hangs forever, right?
Linny-senpai: To prevent that, use -t (timeout). It waits the given number of seconds and moves on if there is no input.
if read -t 5 -p "Type within 5 seconds: " answer; then
    echo "You entered: $answer"
else
    echo
    echo "Time's up"
fi

You can test whether read succeeded with if

read returns "success" when it reads a line, and "failure" on a timeout or end of input (more on that below). Catching this with if read ...; then lets you branch based on whether input arrived.

7. Reading a File Line by Line (while read)

Conclusion: while read line; do ... done < file pulls a file into a variable one line at a time for processing.

Lina: Sometimes I want to process a file line by line, not just keyboard input.
Linny-senpai: For that, the while read combination is the best fit. This is a classic shell-scripting pattern, so memorize the whole shape and you will use it forever.
while read line; do
    echo "Read line: $line"
done < list.txt
Lina: What is the < list.txt part?
Linny-senpai: That is a redirect, meaning "feed the contents of list.txt into read." Each time read reads a line, it stores it in line and loops until there are no more lines. When it reaches the end of the file, read returns "failure," so the loop ends naturally.

A safer form: while IFS= read -r line

In practice you will often see while IFS= read -r line; do ... done < file. The IFS= part prevents leading and trailing whitespace from being stripped, and -r reads backslashes (\) literally. The next section explains why.

8. Two Pitfalls Beginners Hit

Conclusion: A piped while read runs in a separate process so its variables vanish, and without -r backslashes disappear.

Lina: Senpai, I used while read, but a counter I increment inside the loop is back to 0 after the loop... is it a bug?
Linny-senpai: That's a classic. It is not a bug; it is caused by how pipes work. Let's go through it.

Pitfall 1: Variables Inside a Pipe Don't Survive

count=0
cat list.txt | while read line; do
    count=$((count + 1))
done
echo "$count"   # prints 0
Lina: Why is it 0? I'm counting correctly inside.
Linny-senpai: When you connect with a pipe like cat ... | while ..., the while part runs in a separate process (a subshell). Incrementing count there only changes a "clone." The original count is never updated.

Fix: use a redirect instead of a pipe

count=0
while read line; do
    count=$((count + 1))
done < list.txt
echo "$count"   # counts correctly

With the < list.txt redirect, while runs in the same process, so the change to count survives.

Pitfall 2: Without -r, Backslashes Disappear

Lina: And the other one, -r — why do we add it?
Linny-senpai: Without -r, read treats the backslash (\) as special and removes it. For example, reading the path C:\Users gives you C:Users. So when you want to read the input exactly as typed, adding -r is the rule.
# Without -r: the backslashes are gone
echo 'C:\Users\lina' | read path; echo "$path"
# -> C:Userslina

# With -r: read literally
echo 'C:\Users\lina' | read -r path; echo "$path"
# -> C:\Users\lina

When in doubt, add -r

Unless you have a specific reason not to, adding -r to read is the safe choice. Shell script linters (such as ShellCheck) also warn about a read without -r.

9. A Quick Exercise to Review

Lina: I've learned a lot, so I want to write something myself!
Linny-senpai: Great. Here's a small challenge. Write a script that asks for a name and greets the user back.
Exercise: write a greeting script (click for a solution)

Task: Ask "What's your name?", then use the entered name to print "Hello, NAME!"

Sample solution:

#!/bin/bash
read -p "What's your name? " name
echo "Hello, ${name}!"

It shows a prompt with -p and prints the captured value with $name. Wrapping it as ${name} with braces makes the variable boundary clear and safe.

Lina: Done! Show a prompt with read -p, then display it with $name.
Linny-senpai: That's the spirit. read is a short command, but once you have -p, -s, -t, and while read, you can handle almost any "capture input" situation. From here, just keep using it in real scripts to build fluency.

Summary

Key points of the read command

  • read variable stores one line of standard input into a variable
  • -p "message" shows a prompt that asks for input
  • -s hides the input from the screen (good for passwords)
  • -t seconds sets a timeout on the wait for input
  • while read line; do ... done < file processes a file line by line
  • Use a redirect (< file) instead of a pipe, and add -r, for the safe form

Once you master read, your scripts evolve from "things that just run on their own" into "things that interact with the user." Next, head to Shell Scripting Basics to learn how to combine the captured input with conditionals and loops.