Thuta Learning
BasicDevOps & Toolsbeginner

Script Arguments and User Input

What you'll walk away with

  • Explain the core ideas behind Script Arguments and User Input
  • Run the sample code and verify its output
  • Apply the technique correctly to the Tutorial Platform and production scenarios

Build the mental model

When you run a script with arguments, like `./greet.sh alice bob`, bash makes them available inside the script as positional parameters: `$1` is the first argument, `$2` the second, and so on up through `$9` (beyond that you need `${10}`, with braces, since `$10` would be parsed as `$1` followed by a literal `0`), while `$#` tells you how many arguments were passed in total. `$@` and `$*` both nominally mean 'all the arguments,' but they diverge sharply depending on whether you quote them. Unquoted, both word-split the same way and lose any internal structure. Quoted, they behave completely differently: `"$@"` expands to each argument as its own separate, correctly preserved word — even ones containing spaces — while `"$*"` joins every argument into a single combined string using the first character of `$IFS` (a space, by default) as the separator. This is why `"$@"` is almost always the right choice when looping over arguments one at a time. For input that isn't handed in ahead of time as arguments, the `read` builtin pauses execution and stores a line of typed (or piped) input into a variable, which is what lets a script prompt a user interactively. And because arguments and variables are often optional, the `${1:-default}` expansion pattern supplies a fallback value whenever the referenced argument or variable is unset or empty, so the script doesn't crash or silently use a blank string.

Connect it to a real scenario

A backup script might accept a target directory as its first argument but fall back to a sensible default if the user doesn't supply one: `target=${1:-/var/backups}` means the script still works correctly even when invoked with zero arguments. Now suppose that same script also needs to loop over a list of filenames passed as further arguments, some of which — like `"charlie brown"` in the lesson's own example — contain spaces. Looping with unquoted `$*` (or quoted `"$*"`) collapses everything into pieces or a single glued-together string, splitting `"charlie brown"` into two separate words `charlie` and `brown`, exactly as the example output shows. Looping with quoted `"$@"` instead preserves each original argument intact, so `"charlie brown"` stays one item. The same care applies to `read`: capturing a line into a variable and then using it unquoted downstream reintroduces the exact word-splitting risk covered in the previous lesson.

Try the working example

bash
#!/usr/bin/env bash
# Simulate command-line arguments using "set --" (in real use these
# would come from: ./script.sh alice bob "charlie brown")
set -- alice bob "charlie brown"

echo "Argument count: $#"
echo "First argument: $1"
echo "Second argument: $2"

echo 'Looping with unquoted $*:'
for name in $*; do
  echo "  name -> $name"
done

echo 'Looping with quoted "$@":'
for name in "$@"; do
  echo "  name -> $name"
done

echo "Enter your favorite language:"
read -r favorite <<< "bash"
echo "You picked: $favorite"

greeting=${4:-"stranger"}
echo "Hello, $greeting"
You should see
Running this script prints:

Argument count: 3
First argument: alice
Second argument: bob
Looping with unquoted $*:
  name -> alice
  name -> bob
  name -> charlie
  name -> brown
Looping with quoted "$@":
  name -> alice
  name -> bob
  name -> charlie brown
Enter your favorite language:
You picked: bash
Hello, stranger

5-minute try-it

Write a script that uses `set -- ...` to simulate three arguments representing colors, prints how many arguments there are with `$#`, then loops over them twice — once with unquoted `$*` and once with quoted `"$@"` — using a color name that contains a space (like 'light blue') to see the difference.

One important caution

Looping over $@ or $* without quotes (or quoting $* instead of $@) and having arguments with spaces silently split into multiple items

Assuming $1 exists without a default or check, so the script crashes or behaves oddly with an empty string when the caller forgets to pass an argument

GNU Bash Reference Manual — Special ParametersBash / Shell Scripting

Easy traps

  • Looping over $@ or $* without quotes (or quoting $* instead of $@) and having arguments with spaces silently split into multiple items
  • Assuming $1 exists without a default or check, so the script crashes or behaves oddly with an empty string when the caller forgets to pass an argument
  • Validate sample code in a local or test environment before applying it to a production system.

Exercise

Write a script that uses `set -- ...` to simulate three arguments representing colors, prints how many arguments there are with `$#`, then loops over them twice — once with unquoted `$*` and once with quoted `"$@"` — using a color name that contains a space (like 'light blue') to see the difference.

You'll know it worked when: Running this script prints: Argument count: 3 First argument: alice Second argument: bob Looping with unquoted $*: name -> alice name -> bob name -> charlie name -> brown Looping with quoted "$@": name -> alice name -> bob name -> charlie brown Enter your favorite language: You picked: bash Hello, stranger

Script Arguments and User Input | Thuta Learning