The scenario
You're on-call for a small app. Every day, log files land in project/logs/, and your job each morning is to produce project/reports/summary.txt: one line per log file with its error count.
Done by hand, that's opening every file and counting. Done your way, it's a script that uses one tool from nearly every unit:
mkdir -p, paths (unit 2)- writing files with
>and>>(units 3, 5) grep -c(unit 4)- a for loop over a wildcard (units 4, 9)
- a function with
$1(units 8, 9) - redirecting a whole loop's output into a file (unit 5)
First, set the stage.
Code exercise · bash
Run the setup: two directories and two log files with known contents (mon.log has 1 error, tue.log has 2). The final ls confirms the stage is set.
Code exercise · bash
Your turn: the full automation. The starter rebuilds the stage. Now write a function `report` that prints `<filename>: <N> errors` for the file in $1, loop it over every `.log` in project/logs, send the WHOLE loop's output into project/reports/summary.txt, then cat the report. Expected output: ``` project/logs/mon.log: 1 errors project/logs/tue.log: 2 errors ```
Where you go from here
You now hold the everyday toolkit of a working engineer: navigate anywhere, inspect anything, chain small tools into answers, and script away repetition. Three natural next steps:
- Git & GitHub: version control lives entirely in this terminal you now speak fluently.
- Use the shell daily. Take the long way on purpose for two weeks: mkdir instead of right-click, grep instead of scrolling.
- When a task feels repetitive, write the loop. Every script you write pays rent forever.
Quiz
Final check. In the capstone, `done > project/reports/summary.txt` appears once after the loop. Why is this better than putting >> summary.txt on the echo inside the function?