bash: loopsLoops: for, while read, until and retry
Loops repeat work: for walks over a list of words, files or numbers, while read processes a file or command output line by line, and until retries something until it succeeds. break and continue control the flow. Most automation (every host, every log, retry until healthy) is one of these three shapes.
for x in LIST; do ...; done while read -r line; do ...; done < FILE until CMD; do ...; doneCount errors in every rotated app log, generate a reload command per web server, and count attempts.
whileRepeat the body as long as the condition command exits 0.
for x in LIST expands LIST once, before the loop starts: words are split and globs like *.log are matched against the directory, and the body then runs once per resulting word with x set to it. A glob that matches nothing stays as the literal pattern unless shopt -s nullglob is set. while and until are driven by a command's exit status, checked before every iteration: while repeats on 0, until repeats on non-zero. read is that command in the common while read pattern: it reads stdin up to a newline, splits the line on IFS into the named variables and returns 1 at end of file. Every part of a pipeline runs in its own subshell, so in cat file | while read ...; done the loop is a child process and any variable it changes vanishes when it ends. Redirecting into the loop with < file or < <(cmd) keeps it in the current shell. break leaves the innermost loop and continue skips to the next iteration.
for x in a b cLoop over a list of wordsfor f in *.logLoop over matching files (names with spaces are safe)for i in {1..10}Brace range (fixed numbers; use seq or C-style for variables)for ((i=0; i<n; i++))C-style counter loopwhile read -r lineProcess input line by line; -r keeps backslashesIFS=, read -r a bSplit each line on commas instead of whitespaceuntil CMDRepeat until CMD succeeds (retries, waiting for a port)break / continueLeave the loop / skip to the next iterationdone < fileFeed a file into the loop without a subshelldone < <(cmd)Feed command output into the loop without a subshellshopt -s nullglobA glob that matches nothing expands to nothingfor f in $(ls /var/log/app)Command output is split on spaces and newlines and then globbed, so unusual names break apart.
for f in /var/log/app/*; do ... "$f" ...; donecat hosts | while read h; do count=$((count+1)); done; echo $countThe loop runs in a subshell because it's in a pipeline; its variables are lost afterwards.
while read -r h; do ...; done < hostswhile read line; do ssh "$line" uptime; done < hostsssh reads stdin too and swallows the rest of the host list, so only the first host is processed.
while read -r h; do ssh -n "$h" uptime; done < hosts # -n: stdin from /dev/nulluntil curl -f "$url"; do sleep 2; doneNo limit: if the service never comes up, the pipeline hangs until a global timeout kills it.
Count attempts and exit 1 after N tries, or wrap it: timeout 120 bash -c 'until ...; do sleep 2; done'for i in {1..$n}Brace expansion happens before variables are expanded, so it produces the literal {1..5}.
for ((i = 1; i <= n; i++)) # or: for i in $(seq 1 "$n")Try these on a Linux machine of your own. Each task has a hint and a solution.
Print the line count of every .log file in ~/logs, one per line, using a for loop.
Read ~/data/servers.txt (name ip state) and print only the names of servers that are not running.
Write an until loop that waits for the file /tmp/ready to exist, checking every second, and create the file from another terminal (or in the background).
Print the numbers 1 to 10 but skip 5 and stop after 8.
bash: loopsLoops: for, while read, until and retry
Loops repeat work: for walks over a list of words, files or numbers, while read processes a file or command output line by line, and until retries something until it succeeds. break and continue control the flow. Most automation (every host, every log, retry until healthy) is one of these three shapes.
for x in LIST; do ...; done while read -r line; do ...; done < FILE until CMD; do ...; doneCount errors in every rotated app log, generate a reload command per web server, and count attempts.
whileRepeat the body as long as the condition command exits 0.
for x in LIST expands LIST once, before the loop starts: words are split and globs like *.log are matched against the directory, and the body then runs once per resulting word with x set to it. A glob that matches nothing stays as the literal pattern unless shopt -s nullglob is set. while and until are driven by a command's exit status, checked before every iteration: while repeats on 0, until repeats on non-zero. read is that command in the common while read pattern: it reads stdin up to a newline, splits the line on IFS into the named variables and returns 1 at end of file. Every part of a pipeline runs in its own subshell, so in cat file | while read ...; done the loop is a child process and any variable it changes vanishes when it ends. Redirecting into the loop with < file or < <(cmd) keeps it in the current shell. break leaves the innermost loop and continue skips to the next iteration.
for x in a b cLoop over a list of wordsfor f in *.logLoop over matching files (names with spaces are safe)for i in {1..10}Brace range (fixed numbers; use seq or C-style for variables)for ((i=0; i<n; i++))C-style counter loopwhile read -r lineProcess input line by line; -r keeps backslashesIFS=, read -r a bSplit each line on commas instead of whitespaceuntil CMDRepeat until CMD succeeds (retries, waiting for a port)break / continueLeave the loop / skip to the next iterationdone < fileFeed a file into the loop without a subshelldone < <(cmd)Feed command output into the loop without a subshellshopt -s nullglobA glob that matches nothing expands to nothingfor f in $(ls /var/log/app)Command output is split on spaces and newlines and then globbed, so unusual names break apart.
for f in /var/log/app/*; do ... "$f" ...; donecat hosts | while read h; do count=$((count+1)); done; echo $countThe loop runs in a subshell because it's in a pipeline; its variables are lost afterwards.
while read -r h; do ...; done < hostswhile read line; do ssh "$line" uptime; done < hostsssh reads stdin too and swallows the rest of the host list, so only the first host is processed.
while read -r h; do ssh -n "$h" uptime; done < hosts # -n: stdin from /dev/nulluntil curl -f "$url"; do sleep 2; doneNo limit: if the service never comes up, the pipeline hangs until a global timeout kills it.
Count attempts and exit 1 after N tries, or wrap it: timeout 120 bash -c 'until ...; do sleep 2; done'for i in {1..$n}Brace expansion happens before variables are expanded, so it produces the literal {1..5}.
for ((i = 1; i <= n; i++)) # or: for i in $(seq 1 "$n")Try these on a Linux machine of your own. Each task has a hint and a solution.
Print the line count of every .log file in ~/logs, one per line, using a for loop.
Read ~/data/servers.txt (name ip state) and print only the names of servers that are not running.
Write an until loop that waits for the file /tmp/ready to exist, checking every second, and create the file from another terminal (or in the background).
Print the numbers 1 to 10 but skip 5 and stop after 8.