Skip to content

VOL 00 / CH 02 / LESSON 07

2.7 Terminal Integration Exercise ​

Prerequisites: Pages 1 through 5 of this chapter

Estimated time: 20–25 minutes

Exercise environment: Bash 5 on GNU/Linux

You are ready to continue when: you can complete the exercise independently and explain each expansion and redirection

Complete one continuous task from an empty directory. The experiment does not modify startup files in the home directory or depend on /var/log; every output stays inside the directory created by mktemp.

Task 1: Establish Project Skeleton ​

bash
workdir=$(mktemp -d)
printf 'workdir=%s\n' "$workdir"
cd "$workdir"

mkdir -p project/{src,docs,logs,bin}
printf '%s\n' '# Workshop Project' > project/README.md
printf '%s\n' 'first note' > project/docs/notes.txt
printf '%s\n' 'second note' >> project/docs/notes.txt
touch project/logs/app-{01,02,03}.log
find project -print

Checkpoints: Directory structure is complete; notes.txt has two lines; three log files exist.

Task 2: Create a Command Effective Only in the Practice Area ​

bash
cat > project/bin/workshop-status <<'SCRIPT'
#!/bin/sh
printf 'root=%s\n' "$WORKSHOP_ROOT"
find "$WORKSHOP_ROOT" -type f -print
SCRIPT
chmod +x project/bin/workshop-status

export WORKSHOP_ROOT="$workdir/project"
original_path=$PATH
PATH="$workdir/project/bin:$PATH"
export PATH

type -a workshop-status
workshop-status

Checkpoint: type -a points to a temporary directory; child processes can read WORKSHOP_ROOT.

Task 3: Preview Batch Renaming ​

bash
cd "$WORKSHOP_ROOT/logs"
for file in ./*.log; do
  [ -e "$file" ] || continue
  printf 'would rename: %q -> %q\n' "$file" "${file%.log}.bak"
done

Confirm all three targets are correct before executing:

bash
for file in ./*.log; do
  [ -e "$file" ] || continue
  mv -- "$file" "${file%.log}.bak"
done
printf '%s\n' ./*.bak

Checkpoints: Only the file extensions were changed, and the file content remained unchanged. If processing images, renaming does not equate to format conversion.

Task 4: Observe Standard Output and Standard Error ​

bash
cd "$workdir"
sh -c 'printf "normal\n"; printf "problem\n" >&2; exit 7' \
  >out.log 2>err.log || status=$?
printf 'status=%s\n' "${status:-0}"
printf 'stdout: '; cat out.log
printf 'stderr: '; cat err.log

Checkpoints: The exit status is 7, and each file has one line. Then, change the redirection to >all.log 2>&1 and observe how the two lines end up in the same file.

Task 5: Reliably Traverse and Count ​

bash
count=0
while IFS= read -r -d '' file; do
  ((count += 1))
done < <(find project -type f -print0)
printf 'files=%d\n' "$count"

After these steps, expect files=6: the README, notes, custom script, and three logs. out.log and err.log are outside project, so they are excluded. The loop does not propagate the exit status of find inside process substitution; separately check read failures on real directories. NUL-delimited iteration handles spaces and newlines in filenames more reliably than parsing ls. The code uses Bash's process substitution and read -d; if the script must be portable across /bin/sh, macOS, and Linux, the implementation should be reselected to one that is supported across all three platforms, rather than by changing the first line interpreter alone.

Troubleshooting Order ​

  1. pwd: Is it in the expected directory?
  2. printf '<%s>\n' "$variable": Is the variable empty or contains unexpected whitespace?
  3. type -a command: Which command is actually being executed?
  4. ls -ld -- "$path": Does the target exist and does it have sufficient permissions?
  5. printf '%q\n' "$path": What is the expanded path in Bash?
  6. status=$?: Which step failed? Do not run another command before reading the status.

Cleaning and Acceptance ​

bash
cd
ls -ld -- "$workdir"
rm -r -- "$workdir"
PATH=$original_path
export PATH
unset original_path WORKSHOP_ROOT
hash -r 2>/dev/null || true

To check your understanding, repeat all five tasks in a fresh directory without looking at the answers. After completing them, you should be able to explain why variables are quoted, why the -- is used before the path, and why the exercises don't directly modify the Shell startup file.

You can now confirm the current location, inspect command resolution, and review the scope of batch operations before execution. The next chapter uses Git to record file changes so committed states can be compared and restored.

→ Next: What is Git?

Built with VitePress | Software Systems Atlas