read
| Since: | read(基本) | POSIX(sh互換) |
|---|---|---|
| -p / -s / -t / -n / -a(bash拡張オプション) | Bash(bash拡張) |
The read command in shell scripts is a built-in command that reads one line from standard input and stores it in a variable. It is useful in a wide range of situations, including prompting the user for input, reading passwords without displaying them on screen, and processing files line by line. The -p option displays a prompt string before accepting input, and -s reads input silently without echoing characters to the terminal. The while read line pattern is the standard idiom for processing standard input or a file one line at a time.
Basic Syntax
read is used in the form read [options] variable.... When multiple variable names are specified, the input line is split on IFS delimiters and each field is stored in the corresponding variable. If no variable name is given, the input is stored in the special variable REPLY.
| Syntax | Description |
|---|---|
read var | Reads one line from standard input and stores it in the variable var. |
read var1 var2 ... | Splits the line on IFS and stores each field in the corresponding variable in order. Any remaining fields are all stored in the last variable. |
read (no variable name) | Stores the line that was read in the built-in variable REPLY. |
read -r var | Does not interpret backslashes as escape characters. Using -r is recommended whenever reading from a file. |
read -p "string" var | Displays a prompt string before waiting for input (bash only). |
read -s var | Does not echo the input characters to the screen. Used for password input. |
read -t seconds var | Times out if no input is received within the specified number of seconds. The exit status is 1 on timeout. |
read -n count var | Automatically finishes reading after the specified number of characters. No Enter key press is required. |
read -d char var | Uses the specified character as a delimiter instead of a newline. |
read -a array | Splits the input on IFS and stores it in an array (bash only). |
# Basic form of read
read var
# Split into multiple variables (IFS defaults to space, tab, and newline)
read var1 var2 var3
# Standard pattern for reading a file (-r treats backslashes literally)
while IFS= read -r line; do
echo "${line}"
done < filename
# Input with a prompt (bash)
read -p "Enter your name: " name
# Silent input (e.g., for passwords)
read -s -p "Password: " password
echo "" # read -s does not output a newline, so we add one manually
Relationship with IFS
IFS (Internal Field Separator) is a shell variable that defines the delimiter characters used to split input. When read stores a single line into multiple variables, it uses the value of IFS as the delimiter. The default value consists of three characters: space, tab, and newline.
| IFS Setting | Behavior |
|---|---|
| Default (space, tab, newline) | Treats consecutive spaces or tabs as a single delimiter. Leading and trailing whitespace is automatically stripped. |
IFS= (empty string) | Performs no splitting. The entire line is stored as-is in a single variable. Leading and trailing whitespace is preserved. This is the recommended setting when reading files. |
IFS=: (colon) | Splits on colons. Useful for parsing formats like /etc/passwd. |
IFS=$'\t' (tab) | Splits on tabs. Useful for parsing TSV files. |
IFS=, (comma) | Splits on commas. Useful for simple CSV parsing. |
When changing IFS, it is safest to specify it inline immediately before the read command, in the form IFS=delimiter read -r variable. This way the change to IFS is only in effect during the execution of read and does not affect the global shell environment.
# Specifying IFS inline (does not pollute the shell-wide IFS)
IFS=: read -r field1 field2 field3 <<< "aaa:bbb:ccc"
# Reading an entire line with IFS= to preserve whitespace
while IFS= read -r line; do
echo "${line}"
done < data.txt
# Splitting a tab-delimited line with IFS=$'\t'
while IFS=$'\t' read -r col1 col2 col3; do
echo "${col1} / ${col2} / ${col3}"
done < data.tsv
The while read Pattern
To process a file or standard input one line at a time, while IFS= read -r line; do ... done < file is the most commonly used approach. IFS= prevents whitespace trimming, and -r treats backslashes as literal characters.
| Pattern | Description |
|---|---|
while IFS= read -r line; do ... done < file | The most basic pattern, passing a file via redirection. Preserves leading and trailing whitespace on each line. |
command | while IFS= read -r line; do ... done | Pipes command output into the loop. Because the pipe runs in a subshell, variables modified inside the loop are not available in the parent shell. |
while IFS= read -r line; do ... done <<< "$var" | Processes a variable's content line by line using a here string. No subshell is created, so variables are accessible in the parent shell. |
while IFS=$'\t' read -r f1 f2; do ... done < file | Stores each tab-delimited field in a separate variable. Well-suited for TSV parsing. |
while IFS= read -r line || [ -n "$line" ]; do ... done < file | Ensures the last line is not missed even if the file does not end with a newline. |
Sample Code
kof_read_basic.sh
#!/bin/bash
# -----------------------------------------------
# Demonstrates the basic usage of the read command
# using characters from The King of Fighters (KOF)
# -----------------------------------------------
# -----------------------------------------------
# 1. read var — reads one line from standard input into a variable
# -----------------------------------------------
echo "=== KOF Fighter Registration System ==="
echo ""
# Read input and store it in the fighter variable
read -p "Enter the name of the fighter to register: " fighter
echo ""
echo " ${fighter} has entered!"
echo ""
# -----------------------------------------------
# 2. Splitting input into multiple variables with read
# -----------------------------------------------
echo "--- Team Registration (enter 3 names separated by spaces) ---"
echo ""
# Uses the default IFS (space) to split into three variables
read -p "Fighter1 Fighter2 Fighter3: " member1 member2 member3
echo ""
echo " Team lineup:"
echo " 1st: ${member1}"
echo " 2nd: ${member2}"
echo " 3rd: ${member3}"
$ chmod +x kof_read_basic.sh
$ ./kof_read_basic.sh
=== KOF Fighter Registration System ===
Enter the name of the fighter to register: Terry Bogard
Terry Bogard has entered!
--- Team Registration (enter 3 names separated by spaces) ---
Fighter1 Fighter2 Fighter3: Terry Joe Shermie
Team lineup:
1st: Terry
2nd: Joe
3rd: Shermie
kof_read_options.sh
#!/bin/bash
# -----------------------------------------------
# Demonstrates read -p / -s / -t / -n options
# using characters from KOF
# -----------------------------------------------
# -----------------------------------------------
# -p option: displays a prompt before waiting for input
# -----------------------------------------------
echo "=== KOF Ranking Board ==="
echo ""
# -p displays a prompt string (bash only)
# Input is accepted immediately after the prompt on the same line
read -p "Enter your fighter name: " player_name
echo " Welcome, ${player_name}!"
echo ""
# -----------------------------------------------
# -s option: does not echo input to the screen
# -----------------------------------------------
echo "--- Enter your secret special move code ---"
echo ""
# -s hides the input characters (used for passwords and secret codes)
# Combined with -p to display a prompt at the same time
read -s -p "Special move code (hidden): " secret_code
echo "" # read -s does not output a newline after input, so we add one manually
# Show only the length of the input, not the content itself
code_len=${#secret_code}
echo " Special move code accepted (${code_len} characters)"
echo ""
# -----------------------------------------------
# -t option: sets a timeout (in seconds)
# -----------------------------------------------
echo "--- Select a fighter within 3 seconds ---"
echo ""
# -t 3 times out if no input is received within 3 seconds
# The exit status is 1 on timeout
if read -t 3 -p "Fighter selection (3 sec): " chosen_fighter; then
echo ""
echo " You selected ${chosen_fighter}!"
else
echo ""
echo " Timed out. Selecting Kula Diamond as the default."
chosen_fighter="Kula Diamond"
fi
echo ""
# -----------------------------------------------
# -n option: auto-confirms after the specified number of characters
# -----------------------------------------------
echo "--- Select difficulty (1 character): 1=Easy 2=Normal 3=Hard ---"
echo ""
# -n 1 confirms immediately after 1 character without requiring Enter
read -n 1 -p "Difficulty (1/2/3): " difficulty
echo "" # -n does not output a newline after input, so we add one manually
case "${difficulty}" in
1) echo " Difficulty: Easy — have fun practicing with ${chosen_fighter}!" ;;
2) echo " Difficulty: Normal — put ${chosen_fighter}'s skills to the test!" ;;
3) echo " Difficulty: Hard — show the true power of ${chosen_fighter}!" ;;
*) echo " Invalid selection. Difficulty set to Normal." ;;
esac
$ chmod +x kof_read_options.sh $ ./kof_read_options.sh === KOF Ranking Board === Enter your fighter name: Terry Bogard Welcome, Terry Bogard! --- Enter your secret special move code --- Special move code (hidden): Special move code accepted (8 characters) --- Select a fighter within 3 seconds --- Fighter selection (3 sec): Kula Diamond You selected Kula Diamond! --- Select difficulty (1 character): 1=Easy 2=Normal 3=Hard --- Difficulty (1/2/3): 3 Difficulty: Hard — show the true power of Kula Diamond!
kof_while_read_file.sh
#!/bin/bash
# -----------------------------------------------
# Demonstrates file line processing with while read
# using characters from KOF
# -----------------------------------------------
# -----------------------------------------------
# Create a data file
# Format: character name[TAB]team[TAB]nationality
# -----------------------------------------------
data_file="/tmp/kof_fighters.tsv"
# Write tab-delimited data using a here document
cat > "${data_file}" <<'EOF'
Terry Bogard Fatal Fury Team USA
Kyo Kusanagi Japan Team Japan
K' K' Team Unknown
Kula Diamond Anti-K' Team Antarctica
Athena Asamiya Women Fighters Team Japan
EOF
echo "=== KOF Fighter Encyclopedia ==="
echo ""
# -----------------------------------------------
# Split tab-delimited columns into variables with IFS=$'\t' read -r
# - IFS=$'\t' : use tab as the delimiter
# - -r : treat backslashes as literal characters
# - < "${data_file}" : pass the file via redirection
# -----------------------------------------------
count=0
while IFS=$'\t' read -r name team country; do
count=$((count + 1))
printf " %d. %-22s Team: %-22s Nationality: %s\n" \
"${count}" "${name}" "${team}" "${country}"
done < "${data_file}"
echo ""
echo "Registered fighters: ${count}"
echo ""
# -----------------------------------------------
# Example of preserving the full line with IFS= read -r
# Leading and trailing whitespace and tabs are not trimmed
# -----------------------------------------------
echo "=== Raw data check (whitespace preserved with IFS=) ==="
echo ""
# Specifying IFS= stores the entire line as-is in the line variable
while IFS= read -r line; do
echo " |${line}|"
done < "${data_file}"
# Remove the temporary file
rm -f "${data_file}"
$ chmod +x kof_while_read_file.sh $ ./kof_while_read_file.sh === KOF Fighter Encyclopedia === 1. Terry Bogard Team: Fatal Fury Team Nationality: USA 2. Kyo Kusanagi Team: Japan Team Nationality: Japan 3. K' Team: K' Team Nationality: Unknown 4. Kula Diamond Team: Anti-K' Team Nationality: Antarctica 5. Athena Asamiya Team: Women Fighters Team Nationality: Japan Registered fighters: 5 === Raw data check (whitespace preserved with IFS=) === |Terry Bogard Fatal Fury Team USA| |Kyo Kusanagi Japan Team Japan| |K' K' Team Unknown| |Kula Diamond Anti-K' Team Antarctica| |Athena Asamiya Women Fighters Team Japan|
kof_read_interactive.sh
#!/bin/bash
# -----------------------------------------------
# Implements an interactive menu with while read
# using characters from KOF
# -----------------------------------------------
# -----------------------------------------------
# KOF fighter information database (managed as arrays)
# -----------------------------------------------
names=("Terry Bogard" "Kyo Kusanagi" "K'" "Kula Diamond" "Athena Asamiya")
teams=("Fatal Fury Team" "Japan Team" "K' Team" "Anti-K' Team" "Women Fighters Team")
origins=("USA" "Japan" "Unknown" "Antarctica" "Japan")
echo "=== KOF Fighter Search System ==="
echo " Type 'quit' to exit"
echo ""
# -----------------------------------------------
# Use while read to repeatedly accept user input
# - read -p displays the prompt
# - break exits the loop when the input is 'quit'
# -----------------------------------------------
while read -r -p "Enter fighter number (1-5) or 'quit': " input; do
# Exit the loop if 'quit' is entered
if [ "${input}" = "quit" ]; then
echo ""
echo "Exiting the system."
break
fi
# Check that the input is a number (integers only)
if ! echo "${input}" | grep -qE '^[0-9]+$'; then
echo " Please enter a number or 'quit'."
echo ""
continue
fi
# Check that the number is in the range 1-5
if [ "${input}" -lt 1 ] || [ "${input}" -gt 5 ]; then
echo " Please enter a number between 1 and 5."
echo ""
continue
fi
# Arrays are zero-indexed, so adjust the index
idx=$((input - 1))
echo ""
echo " ----------------------------------------"
echo " Name : ${names[$idx]}"
echo " Team : ${teams[$idx]}"
echo " Nationality : ${origins[$idx]}"
echo " ----------------------------------------"
echo ""
done
$ chmod +x kof_read_interactive.sh $ ./kof_read_interactive.sh === KOF Fighter Search System === Type 'quit' to exit Enter fighter number (1-5) or 'quit': 1 ---------------------------------------- Name : Terry Bogard Team : Fatal Fury Team Nationality : USA ---------------------------------------- Enter fighter number (1-5) or 'quit': 4 ---------------------------------------- Name : Kula Diamond Team : Anti-K' Team Nationality : Antarctica ---------------------------------------- Enter fighter number (1-5) or 'quit': quit Exiting the system.
Summary
The read command in shell scripts is a fundamental built-in for reading one line from standard input. Use -p to display a prompt while accepting user input, -s to read passwords and other sensitive input silently, -t to set a timeout, and -n to auto-confirm after a specified number of characters. Specifying multiple variable names splits the input on IFS delimiters and stores each field separately. For reading files line by line, the standard pattern is while IFS= read -r line; do ... done < file, where IFS= prevents whitespace trimming and -r treats backslashes literally. For parsing tab-delimited TSV data, combine IFS=$'\t' with multiple variables. Note that the pipe variant of while read runs in a subshell, so variables updated inside the loop are not accessible in the parent shell. For related idioms, see while / until. For details on IFS and how it interacts with input splitting, see Variables.
If you find any errors or copyright issues, please contact us.