Computing FoundationsThe Command Line › Day 9

Hands-on lab — Day 9: Navigating the Filesystem: Paths, Files, and Permissions

Commands

Setup

cd labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and

Run

bash examples/explore_files.sh
bash starter/explore_files.sh

Test

bash tests/run_tests.sh

File tree

examples/explore_files.sh
expected-output/FIELDS.md
expected-output/sample-macos.txt
metadata.yml
README.md
requirements/README.md
security.md
starter/explore_files.sh
starter/filesystem-worksheet.md
tests/run_tests.sh
troubleshooting.md

Lab README

Day 009 lab — Build and Explore a File Tree

Lesson

Purpose

Day 9's lesson explains the filesystem tree, paths, and permissions. This lab makes them muscle memory: you build a small directory tree inside a safe, temporary workspace, navigate it with pwd/cd/ls, create and move files, and make a file executable with chmod while watching its permission string change from -rw-r--r-- (644) to -rwxr-xr-- (754). Everything happens inside a folder the script creates and then deletes, so you cannot harm anything else on your machine.

Learning objectives

  • Run pwd, cd, and ls -la and read every field of a long listing.
  • Build a nested directory tree with a single mkdir -p command.
  • Create files with touch, move them with mv, and confirm the result.
  • Change a file's permissions with chmod and read the before/after string.
  • Translate a permission string to and from octal notation (e.g. 754).
  • Run an automated test script and interpret its pass/fail output.

Prerequisites

  • The Day 9 lesson (read it first — it explains every concept this lab uses).
  • A terminal: Terminal.app (macOS), any terminal (Linux), or WSL (Windows).
  • No programming experience required; every command is given and explained.

Supported operating systems

  • macOS — fully supported (tested on macOS with Apple Silicon).
  • Linux — fully supported (any distribution with bash, mktemp, and the standard file utilities).
  • Windows — run the scripts unmodified inside WSL (Windows Subsystem for Linux); native PowerShell is not supported for this bash lab.

Hardware requirements

Any computer made in roughly the last 15 years. The lab creates a handful of empty files in a temporary directory and removes them; it needs no meaningful disk, RAM, or GPU.

Required software

  • bash (3.2 or newer — preinstalled on macOS and Linux).
  • Standard utilities only: mktemp, mkdir, touch, cp, mv, rm, ls, chmod, pwd, find — all preinstalled.

Free and open-source options

Everything in this lab is free: bash and every command used are open-source or ship with your OS. No account, API key, or purchase is needed.

Installation

None. Clone the repository (or copy this directory) and you are ready:

cd labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and

File structure

day-009-navigating-the-filesystem-paths-files-and/
├── README.md                       ← you are here
├── metadata.yml                    ← machine-readable lab metadata
├── starter/
│   ├── explore_files.sh            ← YOUR working file (5 exercises)
│   └── filesystem-worksheet.md     ← worksheet for the practice assignment
├── examples/
│   └── explore_files.sh            ← completed reference implementation
├── tests/
│   └── run_tests.sh                ← automated checks
├── expected-output/
│   ├── sample-macos.txt            ← real captured run (macOS, Apple Silicon)
│   └── FIELDS.md                   ← required output lines and platform notes
├── requirements/
│   └── README.md                   ← dependency statement (none beyond the OS)
├── troubleshooting.md
└── security.md

How to run

From this directory:

## 1. See the finished result first
bash examples/explore_files.sh

## 2. Your task: complete the five exercises in the starter, then run it
bash starter/explore_files.sh

## 3. Check your work
bash tests/run_tests.sh

What the commands do

  • bash examples/explore_files.sh — runs the reference script: creates a temporary workspace inside this lab directory with mktemp -d, registers a trap to delete it on exit, then cds into it, builds project/data with mkdir -p, creates files with touch, lists with ls/ls -la, makes run.sh executable with chmod 754 (printing the before/after ls -l), moves report.md into data/ with mv, and finally removes the workspace.
  • bash starter/explore_files.sh — the same skeleton with five exercises left as REPLACE-ME lines; each comment names the exact command to use. Edit the file in any text editor and replace each REPLACE-ME line with the command named beside it.
  • bash tests/run_tests.sh — runs the reference script and checks that it builds the sample tree, makes run.sh executable (verifying both permission strings), prints the required lines, exits 0, and leaves no temporary workspace behind; then checks your starter the same way once you have replaced every REPLACE-ME.

Expected output

See expected-output/sample-macos.txt — a real captured run. The key lines are the two run.sh listings that bracket the chmod:

Before chmod:
-rw-r--r--@ 1 you  staff  0 Jul 12 13:34 run.sh
After chmod:
-rwxr-xr--@ 1 you  staff  0 Jul 12 13:34 run.sh

Your workspace path, owner name, and dates will differ. On macOS an @ may follow the permission string (extended attributes); the nine permission bits before it are what matter. expected-output/FIELDS.md lists every required line and the small macOS/Linux differences.

Validation steps

  1. Run bash examples/explore_files.sh — it must exit without errors and print === Done === at the end.
  2. Confirm the permission string on run.sh changes from -rw-r--r-- to -rwxr-xr-- across the chmod.
  3. Run find . -maxdepth 1 -type d -name 'tmp.explore.*' — it must print nothing, proving the workspace was cleaned up.
  4. Complete the five exercises in starter/explore_files.sh, then run the tests.

Tests

bash tests/run_tests.sh

Expected final line: 15 checks, 0 failure(s). (11 strict checks against the reference script, and 4 structural checks against your starter — which become 11 strict checks once you have replaced every REPLACE-ME). The command exits 0 on success and non-zero on any failure, so it can run in CI.

Cleanup

Nothing to clean up: each script deletes its own temporary workspace on exit via a trap, so no files are left behind. To reset your edits to the starter, restore it from git: git checkout -- starter/explore_files.sh.

Troubleshooting

See troubleshooting.md for the full list (permission errors, No such file or directory, hidden files, mktemp differences, WSL notes).

Security notes

See security.md. Short version: the scripts write only inside a temporary directory they create in this lab folder and then remove; they make no network calls and need no elevated privileges. The file also explains, in general, why rm -rf must be treated with care.

Extension exercises

  1. Give a file three different permission settings in turn (chmod 644, chmod 600, chmod 755), running ls -l after each, and predict the permission string before you check it.
  2. Create a symbolic link with ln -s data/notes.txt shortcut.txt, inspect it with ls -l (note the leading l and the -> arrow), then remove the link and confirm the original file is untouched.
  3. Extend explore_files.sh to also copy a file with cp and print its ls -l, then add a matching check to tests/run_tests.sh.
  • Previous day: Day 8 — the lab in labs/sections/computing-foundations/ for the preceding lesson.
  • Next day: Day 10 — Working with Text: cat, grep, sed, and Pipes (labs/sections/computing-foundations/day-010-working-with-text-cat-grep-sed/, to be written).

Expected output

FIELDS.md

# Required output lines (all platforms)

A correct run of `explore_files.sh` prints, in order (values such as the
workspace path, owner name, and dates will differ on your machine):

1. `=== Build and Explore a File Tree ===`
2. `Workspace: <absolute path ending in tmp.explore.XXXXXX>`
3. `Working directory (pwd): <same workspace path>`
4. `Created nested directories with: mkdir -p project/data`
5. A plain `ls` of `project/` listing `data` and `report.md`
6. A `ls -la` long listing showing `.`, `..`, the `data` directory (leading
   `d`), and `report.md` (leading `-`)
7. `Before chmod:` followed by a line for `run.sh` whose permission string is
   `-rw-r--r--` (octal 644)
8. `After chmod:` followed by a line for `run.sh` whose permission string is
   `-rwxr-xr--` (octal 754)
9. `Moved report.md into data/ with: mv report.md data/`
10. A final `ls` showing `report.md` gone from the current directory and
    present under `data/`
11. `=== Done ===`

After the script finishes, **no `tmp.explore.*` directory remains** under the
lab directory — the trap removes the workspace on exit.

## Platform differences (not fabricated — described)

- **macOS** appends an `@` to the permission string in `ls -l`/`ls -la` output
  when a file carries extended attributes, e.g. `-rw-r--r--@`. This is normal;
  the nine permission bits before the `@` are what matter. `sample-macos.txt`
  in this directory is a real captured run on macOS (Apple Silicon,
  2026-07-12).
- **Linux** prints the same nine bits without the `@` (occasionally a trailing
  `+` when POSIX ACLs are set), and the owner/group columns show your Linux
  user and group. The permission strings `-rw-r--r--` and `-rwxr-xr--` are
  identical across both systems.
- The tests in `tests/run_tests.sh` match the nine permission bits and tolerate
  the trailing `@`/`+`, so they pass on both macOS and Linux.

sample-macos.txt

=== Build and Explore a File Tree ===
Workspace: <repo>/labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and/tmp.explore.cMiSPh

Working directory (pwd): <repo>/labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and/tmp.explore.cMiSPh
Created nested directories with: mkdir -p project/data

Created files: data/notes.txt and report.md
Contents of <repo>/labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and/tmp.explore.cMiSPh/project (ls):
data
report.md

Long listing including hidden entries (ls -la):
total 0
drwxr-xr-x@ 4 you  staff  128 Jul 12 13:34 .
drwx------@ 3 you  staff   96 Jul 12 13:34 ..
drwxr-xr-x@ 3 you  staff   96 Jul 12 13:34 data
-rw-r--r--@ 1 you  staff    0 Jul 12 13:34 report.md

Before chmod:
-rw-r--r--@ 1 you  staff  0 Jul 12 13:34 run.sh
After chmod:
-rwxr-xr--@ 1 you  staff  0 Jul 12 13:34 run.sh
The permission string changed to -rwxr-xr-- (octal 754): the execute bit is now set.

Moved report.md into data/ with: mv report.md data/
Current directory now contains (ls):
data
run.sh
data/ now contains (ls data):
notes.txt
report.md

=== Done ===
The trap will now remove <repo>/labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and/tmp.explore.cMiSPh, leaving nothing behind.

Source files

examples/explore_files.sh (2205 bytes)
#!/usr/bin/env bash
# Day 009 lab — completed reference implementation.
# Builds a small sample directory tree inside a temporary workspace created
# UNDER this lab directory, navigates it with pwd/cd/ls, creates and moves
# files, makes one file executable with chmod (showing the before/after
# `ls -l`), and then removes the whole temporary tree on exit via a trap.
#
# Nothing outside the temporary workspace is ever touched. Safe to re-run.
set -euo pipefail

# The lab directory is the parent of this script's directory (examples/..).
lab_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

# Create the temporary workspace INSIDE the lab directory, and register a
# trap so it is deleted whether the script succeeds, fails, or is interrupted.
workspace="$(mktemp -d "${lab_dir}/tmp.explore.XXXXXX")"
cleanup() { rm -rf "${workspace}"; }
trap cleanup EXIT

echo "=== Build and Explore a File Tree ==="
echo "Workspace: ${workspace}"
echo

# --- 1. Where are we, and build a small tree -------------------------------
cd "${workspace}"
echo "Working directory (pwd): $(pwd)"
mkdir -p project/data
echo "Created nested directories with: mkdir -p project/data"
echo

# --- 2. Create files and list the tree -------------------------------------
cd project
touch data/notes.txt report.md
echo "Created files: data/notes.txt and report.md"
echo "Contents of $(pwd) (ls):"
ls
echo
echo "Long listing including hidden entries (ls -la):"
ls -la
echo

# --- 3. Make a file executable and show the before/after -------------------
touch run.sh
chmod 644 run.sh          # normalize starting permissions for a stable demo
echo "Before chmod:"
ls -l run.sh
chmod 754 run.sh          # owner rwx, group r-x, other r-- => octal 754
echo "After chmod:"
ls -l run.sh
echo "The permission string changed to -rwxr-xr-- (octal 754): the execute bit is now set."
echo

# --- 4. Move a file and confirm its new location ---------------------------
mv report.md data/
echo "Moved report.md into data/ with: mv report.md data/"
echo "Current directory now contains (ls):"
ls
echo "data/ now contains (ls data):"
ls data
echo

echo "=== Done ==="
echo "The trap will now remove ${workspace}, leaving nothing behind."
metadata.yml (626 bytes)
lesson_id: D009
day: 9
kind: command-line-inspection
languages: [bash]
setup_commands:
  - cd labs/sections/computing-foundations/day-009-navigating-the-filesystem-paths-files-and
run_commands:
  - bash examples/explore_files.sh
  - bash starter/explore_files.sh
test_commands:
  - bash tests/run_tests.sh
cleanup_commands:
  - 'git checkout -- starter/explore_files.sh  # optional: reset your work'
requires_network: false
requires_api_key: false
estimated_minutes: 30
last_executed: '2026-07-12'
executed_on: 'macOS (Apple Silicon), bash tests/run_tests.sh → 15 checks, 0 failure(s), exit 0; no tmp.explore.* left behind'
requirements/README.md (560 bytes)
# Dependencies — Day 009 lab

**None beyond a POSIX shell.** This lab intentionally has zero installable
dependencies:

- `bash` ≥ 3.2 (preinstalled on macOS and every mainstream Linux distribution)
- Standard OS utilities: `mktemp`, `mkdir`, `touch`, `cp`, `mv`, `rm`, `ls`,
  `chmod`, `pwd`, and `find` — all part of the base system.

There is deliberately no `requirements.txt`/`package.json` here; the lab must
run on a factory-fresh machine. Windows users run the scripts inside WSL
(Windows Subsystem for Linux), which provides the same utilities.
starter/explore_files.sh (2595 bytes)
#!/usr/bin/env bash
# Day 009 lab — build and explore a file tree (YOUR working file).
#
# The workspace machinery (a temporary directory created UNDER this lab
# directory, plus a trap that deletes it on exit) is already written for you
# and is SAFE: nothing outside the workspace is ever touched.
#
# Your task: complete the five numbered exercises below. Each one names the
# EXACT command to use in its comment. Replace the single placeholder line in
# each exercise (the one that echoes a marker) with that command. The completed
# reference version is in examples/explore_files.sh — try it yourself first,
# then compare.
#
# Note: this starter uses `set -u` (not the stricter `set -euo pipefail` of the
# reference) so that it still runs to completion while exercises are only partly
# filled in. Once every placeholder is replaced, it behaves exactly like the
# reference.
set -u

lab_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
workspace="$(mktemp -d "${lab_dir}/tmp.explore.XXXXXX")"
cleanup() { rm -rf "${workspace}"; }
trap cleanup EXIT

echo "=== Build and Explore a File Tree ==="
echo "Workspace: ${workspace}"
echo

cd "${workspace}"

# --- Exercise 1: print the working directory -------------------------------
# Replace the next line with the command:  pwd
echo -n "Working directory (pwd): "
echo "REPLACE-ME-1"
echo

# --- Exercise 2: build a nested directory tree -----------------------------
# Replace the next line with the command:  mkdir -p project/data
echo "REPLACE-ME-2"
echo "Created nested directories with: mkdir -p project/data"
echo

cd project

# --- Exercise 3: create two empty files ------------------------------------
# Replace the next line with the command:  touch data/notes.txt report.md
echo "REPLACE-ME-3"
echo "Contents of $(pwd) (ls):"
ls
echo
echo "Long listing including hidden entries (ls -la):"
ls -la
echo

# --- Exercise 4: make a file executable ------------------------------------
touch run.sh
chmod 644 run.sh          # normalize starting permissions (given)
echo "Before chmod:"
ls -l run.sh
# Replace the next line with the command:  chmod 754 run.sh
echo "REPLACE-ME-4"
echo "After chmod:"
ls -l run.sh
echo

# --- Exercise 5: move a file into the data directory -----------------------
# Replace the next line with the command:  mv report.md data/
echo "REPLACE-ME-5"
echo "Moved report.md into data/ with: mv report.md data/"
echo "Current directory now contains (ls):"
ls
echo "data/ now contains (ls data):"
ls data
echo

echo "=== Done ==="
echo "The trap will now remove ${workspace}, leaving nothing behind."
starter/filesystem-worksheet.md (1550 bytes)
# Filesystem worksheet — Day 009

Fill in every value from your own machine using the commands from the
lesson. Keep this file — Week 2's shell-scripting lessons build on these
skills.

## 1. Your home directory

Run `cd ~` then `pwd`.

| Question | Your answer | Command you used |
| -------- | ----------- | ---------------- |
| Absolute path of your home directory |            | `cd ~ ; pwd`     |

## 2. The same file, two ways

Create a file (for example, `~/day9/hello.txt` via `mkdir -p ~/day9 && touch ~/day9/hello.txt`).
Then write its location two ways and confirm both reach the same file.

| Question | Your answer |
| -------- | ----------- |
| Absolute path to the file (starts with `/`) |            |
| Relative path to the file from one directory above it |            |
| Command you ran to confirm both point at the same file (e.g. `ls -l <path>`) |            |

## 3. A permission you set

Make a file executable: `chmod 754 ~/day9/hello.txt` (or your own file), then
`ls -l` it.

| Question | Your answer |
| -------- | ----------- |
| Full permission string from `ls -l` (e.g. `-rwxr-xr--`) |            |
| Octal number for that string |            |
| Owner triad → octal (show the arithmetic, e.g. r+w+x = 4+2+1 = 7) |            |
| Group triad → octal (show the arithmetic) |            |
| Other triad → octal (show the arithmetic) |            |

## 4. In your own words

In two or three sentences, explain why the execute (`x`) bit is what
separates a plain data file from a runnable script.

_Your answer:_
tests/run_tests.sh (3827 bytes)
#!/usr/bin/env bash
# Tests for the Day 009 lab. Run from the lab directory:
#   bash tests/run_tests.sh
#
# Verifies that the reference script builds the sample tree, makes a file
# executable (before/after permission strings), prints the required lines,
# exits 0, and leaves NOTHING behind (its temporary workspace is removed).
# The starter is checked the same way once its exercises are completed.
set -u

lab_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
failures=0
checks=0

check() {
  local label="$1" ok="$2"
  checks=$((checks + 1))
  if [ "${ok}" = "yes" ]; then
    echo "  ok: ${label}"
  else
    echo "  FAIL: ${label}"
    failures=$((failures + 1))
  fi
}

count_workspaces() {
  # How many leftover temp workspaces exist directly under the lab directory.
  find "${lab_dir}" -maxdepth 1 -type d -name 'tmp.explore.*' 2>/dev/null | wc -l | tr -d ' '
}

run_script_checks() {
  local script="$1" strict="$2" output before after
  echo "Testing ${script} ..."

  before="$(count_workspaces)"
  if ! output="$(bash "${script}" 2>&1)"; then
    check "script exits successfully" "no"
    echo "${output}" | sed 's/^/    /'
    return
  fi
  check "script exits successfully" "yes"
  after="$(count_workspaces)"

  echo "${output}" | grep -q '^=== Build and Explore a File Tree ===$' \
    && check "prints the lab header" "yes" || check "prints the lab header" "no"
  echo "${output}" | grep -q '^=== Done ===$' \
    && check "prints the done footer" "yes" || check "prints the done footer" "no"

  # Leaves nothing behind: no new workspace directory remains.
  if [ "${after}" -le "${before}" ]; then
    check "removes its temporary workspace (leaves nothing behind)" "yes"
  else
    check "removes its temporary workspace (leaves nothing behind)" "no"
  fi

  if [ "${strict}" = "strict" ]; then
    # The sample tree was built: mkdir and a listing that includes data/.
    echo "${output}" | grep -q 'mkdir -p project/data' \
      && check "builds the nested directory tree" "yes" || check "builds the nested directory tree" "no"
    echo "${output}" | grep -Eq '(^| )data( |$)' \
      && check "sample tree lists the data directory" "yes" || check "sample tree lists the data directory" "no"

    # A file became executable: before shows no x for owner, after shows -rwx.
    echo "${output}" | grep -q '^Before chmod:$' \
      && check "shows the 'Before chmod:' listing" "yes" || check "shows the 'Before chmod:' listing" "no"
    echo "${output}" | grep -q '^After chmod:$' \
      && check "shows the 'After chmod:' listing" "yes" || check "shows the 'After chmod:' listing" "no"
    echo "${output}" | grep -q -- '-rw-r--r--.*run\.sh' \
      && check "before: run.sh is not executable (-rw-r--r--)" "yes" || check "before: run.sh is not executable (-rw-r--r--)" "no"
    echo "${output}" | grep -q -- '-rwxr-xr--.*run\.sh' \
      && check "after: run.sh is executable (-rwxr-xr--, octal 754)" "yes" || check "after: run.sh is executable (-rwxr-xr--, octal 754)" "no"

    # A file was moved into data/.
    echo "${output}" | grep -q 'Moved report.md into data/\|report.md into data' \
      && check "moves report.md into data/" "yes" || check "moves report.md into data/" "no"
  fi
}

run_script_checks "${lab_dir}/examples/explore_files.sh" strict

# The starter ships with REPLACE-ME placeholders on purpose; once the learner
# has replaced them all, hold their script to the same strict standard.
if grep -q 'REPLACE-ME' "${lab_dir}/starter/explore_files.sh"; then
  echo "Note: starter/explore_files.sh still has unfinished exercises — testing structure only."
  run_script_checks "${lab_dir}/starter/explore_files.sh" lenient
else
  run_script_checks "${lab_dir}/starter/explore_files.sh" strict
fi

echo
echo "${checks} checks, ${failures} failure(s)."
[ "${failures}" -eq 0 ]

Troubleshooting

Troubleshooting — Day 009 lab

Permission denied when you run ./run.sh

The execute bit is not set. Either run it through bash (bash run.sh) or make it executable first: chmod +x run.sh (or chmod 754 run.sh), then check with ls -l run.sh that an x now appears in the permission string.

No such file or directory

You are using a relative path from the wrong place. Run pwd to see where you are, then either cd to the right directory or use an absolute path. In the starter, this also appears briefly if you run the script before completing Exercise 2 (mkdir -p project/data) — the later cd project then has nothing to enter. Completing the exercises removes the message.

The starter prints REPLACE-ME ... lines

Those are the unfinished exercises. Open starter/explore_files.sh in a text editor and replace each line that prints REPLACE-ME with the exact command named in the comment beside it (pwd, mkdir -p project/data, touch data/notes.txt report.md, chmod 754 run.sh, mv report.md data/).

ls does not show a file whose name starts with a dot

Hidden files (dot-files) are skipped by plain ls. Use ls -a or ls -la to reveal them.

macOS shows an @ after the permission string

On macOS, ls -l appends @ to a file that carries extended attributes, e.g. -rw-r--r--@. This is normal — the nine permission bits before the @ are the ones that matter, and the tests ignore the trailing @.

mktemp behaves differently or fails

The scripts call mktemp -d "${lab_dir}/tmp.explore.XXXXXX", which works on both macOS and Linux. If you are on a minimal system without mktemp, install the core utilities (coreutils) or run inside WSL.

A tmp.explore.* directory is left behind

Normally the trap ... EXIT removes it. A leftover only appears if the script was killed with an uncatchable signal (kill -9). Delete it manually after checking it is a tmp.explore.* directory in this lab folder: rm -rf tmp.explore.* (run from the lab directory, and read the path first).

Windows: bash is not recognized

Use WSL (wsl --install, then open Ubuntu and run the commands there). Native PowerShell does not run these bash scripts.

Security notes

Security notes — Day 009 lab

  • Where the scripts write. Both examples/explore_files.sh and starter/explore_files.sh write only inside a single temporary directory they create with mktemp -d under this lab directory (named tmp.explore.XXXXXX). They cd into it, build a small tree of empty files there, and nowhere else. A trap cleanup EXIT removes that directory when the script finishes, fails, or is interrupted, so the lab leaves nothing behind. Nothing outside the workspace is created, modified, or deleted.
  • No network, no privileges. The scripts make no network connections, need no sudo, and change no system settings. Everything runs as your normal user on files your user owns.
  • About rm -rf in general. The cleanup step uses rm -rf on the exact workspace path the script itself just created — a safe, bounded use. In general, though, rm -rf is the most dangerous command a beginner runs: it deletes an entire directory tree immediately, with no Trash and no undo, and a wrong or mistyped path (especially one beginning with /, or one built from an empty variable) can erase far more than intended. The habits that keep you safe: read any rm -rf command in full before pressing Return, confirm the target with pwd/ls first, never run it on a path you have not verified, and be extra careful when the path comes from a variable in a script. In this lab the target is fixed and self-created, which is exactly the kind of bounded use that is safe.
  • Read before running. Both scripts are short and commented — read them first. Running unread shell scripts is a common way developers get compromised; every lab script in this course is small enough to read and understand before executing.