Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Loops and Functions  ›  Lesson

for Loops: Once per Item

for 12 minA for loop runs its body once for each word in a list, which can come from an array, arguments, a file pattern, a brace range or an arithmetic counter.

for Loops: Once per Item

backup.sh should now make one archive per folder, so a broken photo folder does not spoil the notes backup. Writing the tar line three times would work until someone adds a fourth folder. A for loop runs the same body once for each item, however many there are.

The rule

for name in list; do body; done: the body runs once per word.

for dir in "${dirs[@]}"; do
    name="${dir##*/}"
    tar -czf "$dest/${name// /_}-$stamp.tar.gz" "$dir"
    echo "Packed $dir"
done

On each pass, dir holds the next item, then the body runs. The list can come from many places:

for dir in "${dirs[@]}"; do ...           # an array
for dir in "$@"; do ...                   # the script's arguments
for dir; do ...                           # short for: in "$@"
for f in "$dest"/*.tar.gz; do ...         # files matching a pattern
for n in {1..5}; do ...                   # a brace range: 1 2 3 4 5
for (( i = 0; i < 3; i++ )); do ...       # a counter: 0 1 2

The file pattern form is the safe way to loop over files: each matching name arrives whole, spaces and all. Avoid for f in $(ls): the output of ls is split on spaces, so My Notes.txt becomes two items. One more surprise: if a pattern matches nothing, the loop runs once with the pattern itself, such as the literal text *.log. Guard with [[ -e "$f" ]] || continue.

The shortcut

Expand the list first, then count the words. Before reading the body, write out exactly what the list becomes after quoting and expansion. The number of words is the number of passes.

for x in a "b c" dStep 1 of 4
  1. Expand the list

    Three words: a, b c (the quotes keep it together) and d.

Drills

Answer fast — trust the rule.

quick drill

How many times does the body run in for x in a "b c" d; do echo "$x"; done?

quick drill

How many passes does for n in {1..4} make?

quick drill

Which values does i take in for (( i = 0; i < 3; i++ ))?

quick drill

In a folder with no .log files, what does for f in *.log; do echo "[$f]"; done print?

quick drill

Why is for f in $(ls) a poor way to loop over files?

Remember

  • for name in list; do body; done: once per word.
  • Expand the list first, then count the words.
  • Loop over files with a pattern, never $(ls); an unmatched pattern stays literal.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainOne archive per folder

Instead of one big archive, backup.sh should make a separate archive for each folder in the dirs array (one of which is My Photos). Write the loop and explain what the loop variable holds on each pass, why the list must be "${dirs[@]}", and why for f in $(ls) is a bad way to loop over files.