Bash Scripting 03 ๐ง User Input โ Reading environment variables and interactive prompts
The previous chapter covered the variable types and the declare attributes. This chapter covers the mechanisms that populate the variables from the outside: the environment variables inherited from the parent process and the interactive prompts that read the user’s input. In Bash, the environment variables are the exported variables that the shell receives from the parent. The read builtin is the mechanism for the interactive prompt. The critical distinction is between the environment variable ($VAR that the script inherits) and the local variable (VAR=value that the script sets). The read builtin has the options (-p, -s, -n, -t, -r) that control the prompt, the echo, the length, the timeout, and the backslash handling. The IFS variable controls the field splitting, and the misuse of the read without the IFS is the source of the leading/trailing whitespace issues.
Key point: The environment variables are the exported variables from the parent, accessed with the $VAR. The read builtin reads the line from the standard input and assigns the words to the variables. The read -p "prompt" VAR displays the prompt. The read -s VAR hides the input (for the passwords). The read -n N VAR reads exactly N characters. The read -t T VAR times out after T seconds. The read -r VAR prevents the backslash interpretation. The IFS= read -r line is the correct form for reading the raw line.
Why user input requires a specific mental model
The environment problem. The environment variables are not the same as the shell variables. The VAR=value in the parent is the shell variable, not the environment. The child process (the script) does not see it unless the parent exported it. The export VAR=value marks the variable for the inheritance. The env command lists the environment, and the set lists the shell variables. The printenv VAR shows the environment variable .
The read problem. The read VAR reads the line from the standard input, splits it on the IFS (the default whitespace), and assigns the first word to the VAR (and the remaining words to the remaining variables, if any). The read VAR1 VAR2 assigns the first word to the VAR1 and the rest of the line to the VAR2. The read -a ARRAY assigns the words to the array. The read without the variable name assigns to the REPLY .
The IFS problem. The IFS is the internal field separator. The default is the space, the tab, and the newline. The read splits on the IFS. The IFS= read -r line clears the IFS and preserves the leading and trailing whitespace. The read -r line without the IFS= strips the leading and trailing whitespace. The raw line reading is the common use case for the config files .
The prompt problem. The read -p "Enter the name: " NAME displays the prompt and reads the input. The prompt goes to the standard error, not the standard output. The read -s suppresses the echo, which is the required for the passwords. The read -t 5 times out after the 5 seconds, and the $? returns the 142 (the 128 + 14 for the SIGALRM) .
The validation problem. The read does not validate the input. The user can enter the empty string, the spaces, the malicious characters. The script must validate the input: the [[ -z "$VAR" ]] for the empty, the [[ "$VAR" =~ ^[0-9]+$ ]] for the numeric, the case for the allowed values. The validation is the script’s responsibility, not the read‘s.
The trade-off. The read is the simple and the standard. The getopts (the chapter 126 in the LFCS series) is the correct for the command-line arguments. The environment variables are the correct for the secrets (the CI/CD) and the configuration. The interactive prompt is the correct for the scripts that require the human interaction.
a. The environment variables
The environment variables are the exported variables from the parent.
#!/bin/bash
echo "HOME: $HOME"
echo "USER: $USER"
echo "PATH: $PATH"
echo "SHELL: $SHELL"
The $HOME, the $USER, the $PATH, and the $SHELL are the standard environment variables. The printenv lists the environment. The env is the same. The set lists the shell variables and the functions.
The custom environment variable.
#!/bin/bash
# The parent exports the variable
export APP_ENV="production"
./script.sh
# The script reads the $APP_ENV
# The script inherits the environment
echo "Env: $APP_ENV"
# production
The export APP_ENV="production" makes the variable visible to the child. The script reads the $APP_ENV. The unexported variable is the invisible.
The environment in the systemd service.
# /etc/systemd/system/myapp.service
[Service]
Environment="APP_ENV=production"
EnvironmentFile=/etc/myapp/env
ExecStart=/usr/local/bin/myapp
The Environment= is the inline. The EnvironmentFile= is the file. The systemd passes the environment to the service. The service reads the $APP_ENV .
b. The read builtin and the prompt
The read reads the line from the standard input.
#!/bin/bash
read -p "Enter the name: " NAME
echo "Hello, $NAME"
The read -p displays the prompt and reads the input. The $NAME is the variable.
The password prompt.
#!/bin/bash
read -s -p "Enter the password: " PASSWORD
echo
echo "Password length: ${#PASSWORD}"
The -s suppresses the echo. The echo after the read prints the newline (the -s does not print it).
The timeout.
#!/bin/bash
if read -t 5 -p "Enter the value (5s): " VALUE; then
echo "You entered: $VALUE"
else
echo "Timeout"
fi
The -t 5 times out after the 5 seconds. The $? returns the non-zero. The if checks the result.
The exact character count.
#!/bin/bash
read -n 1 -p "Continue? (y/n) " ANSWER
echo
echo "You chose: $ANSWER"
The -n 1 reads exactly one character. The echo prints the newline (the read -n does not wait for the Enter).
c. The IFS and the raw line
The IFS= read -r line preserves the leading and trailing whitespace.
#!/bin/bash
# The config file with the spaces
while IFS= read -r line; do
echo "[$line]"
done < /etc/config.txt
The IFS= clears the field separator. The -r prevents the backslash interpretation. The line includes the leading and trailing whitespace. The [$line] shows the exact boundaries.
The read without the IFS=.
#!/bin/bash
# The read without the IFS
read -r line
# The leading and trailing whitespace is stripped
The read -r without the IFS= strips the whitespace. The IFS= read -r preserves it. The difference is the IFS assignment before the read.
The multiple variables.
#!/bin/bash
read -p "Enter name and age: " NAME AGE
echo "Name: $NAME, Age: $AGE"
# Input: Alice 30
# The NAME is "Alice", the AGE is "30"
The read NAME AGE assigns the first word to the NAME and the rest of the line to the AGE. The last variable gets the rest (including the spaces).
Complete Example Session
# ============================================
# PART 1: THE ENVIRONMENT VARIABLES
# ============================================
echo "HOME: $HOME"
echo "USER: $USER"
echo "PATH: $PATH"
# ============================================
# PART 2: THE CUSTOM ENVIRONMENT
# ============================================
export APP_ENV="prod"
bash -c 'echo "Env: $APP_ENV"'
# Env: prod
# ============================================
# PART 3: THE SIMPLE READ
# ============================================
read -p "Enter name: " NAME
echo "Hello, $NAME"
# ============================================
# PART 4: THE PASSWORD
# ============================================
read -s -p "Password: " PASS
echo
echo "Length: ${#PASS}"
# ============================================
# PART 5: THE TIMEOUT
# ============================================
if read -t 5 -p "Value (5s): " VAL; then
echo "Got: $VAL"
else
echo "Timeout"
fi
# ============================================
# PART 6: THE SINGLE CHARACTER
# ============================================
read -n 1 -p "Continue? (y/n) " ANS
echo
echo "Choice: $ANS"
# ============================================
# PART 7: THE RAW LINE
# ============================================
while IFS= read -r line; do
echo "[$line]"
done < /etc/config.txt
# ============================================
# PART 8: THE MULTIPLE VARIABLES
# ============================================
read -p "Name and age: " NAME AGE
echo "Name: $NAME, Age: $AGE"
# ============================================
# PART 9: THE VALIDATION
# ============================================
read -p "Count: " COUNT
if [[ "$COUNT" =~ ^[0-9]+$ ]]; then
echo "Valid: $COUNT"
else
echo "Invalid"
fi
The nine parts trace the user input: the environment, the custom environment, the simple read, the password, the timeout, the single character, the raw line, the multiple variables, and the validation.
Quick Reference
The read Options
| Option | Purpose |
|---|---|
-p | The prompt |
-s | The silent (the password) |
-n N | Read N characters |
-t T | The timeout in seconds |
-r | The raw (no backslash) |
-a | The array |
-d | The delimiter |
The Environment
| Command | Purpose |
|---|---|
export VAR | Mark for the children |
printenv | List the environment |
env | The same |
set | The shell variables |
The IFS Usage
| Form | Effect |
|---|---|
read -r line | Strips the whitespace |
IFS= read -r line | Preserves the whitespace |
IFS=: read -r a b | Splits on the : |
The Validation
| Test | Purpose |
|---|---|
[[ -z "$VAR" ]] | The empty |
[[ "$VAR" =~ ^[0-9]+$ ]] | The numeric |
case | The allowed values |
Best Practices
โ Do This:
read -r -p "Name: " NAME
<!-- Use the -r for the backslash --> # โ
while IFS= read -r line; do ...; done < file
<!-- Use the IFS= for the raw lines --> # โ
if [[ "$COUNT" =~ ^[0-9]+$ ]]; then ... fi
<!-- Validate the numeric input --> # โ
โ Don’t Do This:
read -p "Name: " NAME
<!-- The backslash is the interpreted --> # โ
read line
<!-- The leading whitespace is stripped --> # โ
# Trust the input without the validation
<!-- The malicious or empty input --> # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The whitespace stripped | No IFS= | IFS= read -r |
| The backslash interpreted | No -r | read -r |
| The password visible | No -s | read -s |
| The numeric check fails | No validation | [[ =~ ]] |
| The environment not visible | Not exported | export VAR |
Real-World Examples
1. The Prompt
read -p "Name: " NAME
2. The Password
read -s -p "Password: " PASS
3. The Timeout
read -t 5 -p "Value: " VAL
4. The Single Character
read -n 1 -p "Continue? " ANS
5. The Raw Line
IFS= read -r line
6. The File Loop
while IFS= read -r line; do echo "$line"; done < file
7. The Multiple Variables
read -p "Name and age: " NAME AGE
8. The Validation
[[ "$VAL" =~ ^[0-9]+$ ]]
9. The Export
export APP_ENV="prod"
10. The Print Environment
printenv | grep APP_
Visual
The Environment Inheritance
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Parent shell โ
โ โโโ APP_ENV="prod" (exported) โ
โ โโโ LOCAL="local" (not exported) โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ ./script.sh
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ The script (child) โ
โ โโโ APP_ENV (visible) โ
โ โโโ LOCAL (not visible) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The read Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ read -p "Prompt: " VAR โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ The prompt to the stderr โ
โ The input from the stdin โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ The line split on the IFS โ
โ The words assigned to the variables โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| The environment | export VAR |
| The list | printenv |
| The read | read VAR |
| The prompt | read -p |
| The password | read -s |
| The timeout | read -t N |
| The raw line | IFS= read -r |
| The validation | [[ =~ ]] |
Key takeaways:
- The environment variables are the exported. The
export VARmakes the variable visible to the child. Theprintenvlists the environment. The unexported variable is the invisible. - The
readreads the line and splits on theIFS. Theread -pprompts. Theread -shides. Theread -ttimes out. The-nreads the characters. - The
IFS= read -rpreserves the whitespace. Theread -rstrips it. The raw line reading is the correct for the config files and the text processing. - The validation is the script’s responsibility. The
readdoes not validate. The[[ =~ ]]for the numeric, the-zfor the empty, thecasefor the allowed values. - The environment is the secret mechanism. The CI/CD variables, the systemd
Environment=, the.envfiles. The environment variables are the standard for the configuration and the secrets.
Remember: The export is the environment. The read is the input. The IFS= is the raw. The -r is the backslash. The validation is the safety. The exam tests the read options and the environment variables.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!