Loops & Functions

Loops

for f in *.log; do echo "$f"; done

for i in $(seq 1 5); do echo "$i"; done

while read -r line; do echo "$line"; done < input.txt

until ping -c1 host &>/dev/null; do sleep 2; done

for loops over a fixed list of items - in the first example, every filename matching .log (the shell expands that wildcard before the loop even starts, the same globbing mechanism you used with find and ls). while keeps going as long as its condition stays true; until is while's mirror image, looping as long as its condition stays false* - here, retrying every 2 seconds until a host finally responds to ping.

Functions

greet() {
  local who="$1"
  echo "Hi, $who"
  return 0
}
greet Alice

A function bundles reusable logic under a name, exactly like the scripts and commands you already know, but living inside a single script file. local matters more than it looks: without it, who would be a global variable, silently visible (and overwritable) from anywhere else in the script - local scopes it to just this function, preventing one function's temporary variable from clashing with another's.

case statement:

case "$1" in
  start) echo starting ;;
  stop)  echo stopping ;;
  *)     echo 'usage: start|stop' ;;
esac

case is a cleaner alternative to a long chain of if/elif when you're comparing one value against several fixed possibilities - the *) branch acts as a catch-all default, matching anything not covered by the earlier patterns, similar in spirit to else.

Tip: while read -r line; do ...; done < file is the standard, safe idiom for processing a text file line by line in bash - worth memorizing as a unit rather than reasoning it out each time. The -r flag matters more than it looks: without it, read treats backslashes in the input as escape characters and quietly mangles them (a line containing a literal \n or a Windows path like C:\Users would get corrupted); -r ("raw") disables that, reading each line exactly as written.