# Exercise: The Bakery's Orders

Answer a bakery owner's questions about a year of orders with pipelines, then rank the cities with tee, build a lowercase mailing list, keep separate logs of results and errors, and delete only the canceled receipts with xargs, while a check script tells you what's done.

Apprentice · Unix · Linux · Updated November 10, 2026

Bea has the orders from Bluebird Bakery's first year online, 2024, and a list of questions. How many orders came in? What sold best? How many different customers are there to email? She also wants a ranking of the cities saved for her accountant, a mailing list, a log of what worked and a log of what failed, and the receipts of canceled cakes deleted without losing a paid one. Every job is a pipeline from this chapter. A check script looks at the bakery folder and your answers, and tells you which jobs are done.

## Before you start

You need a terminal: the Terminal app on a Mac, or Ubuntu on Linux or in WSL on Windows. The check runs with **bats**, a small program that runs checks written for bash. If `bats --version` doesn't print a version number yet, install it:

```bash
sudo apt install bats       # Ubuntu, and Ubuntu in WSL
brew install bats-core      # a Mac, with Homebrew
```

`sudo` asks for your password, the one you use to sign in; nothing shows on the screen while you type it.

## Get the exercise code

Open this lesson's GitHub repository, [github.com/ask-codey/exercise-bash-the-bakerys-orders](https://github.com/ask-codey/exercise-bash-the-bakerys-orders), also linked from the **Exercise** box beside the lesson. Click **Code**, then **Download ZIP**, and unzip it into your `terminal-practice` folder. Or clone it with Git.

The folder holds:

- `bakery/orders.csv`: 2024's orders, one a line, with the same columns as in the lessons: `order,date,customer,email,city,item,qty,total`.
- `bakery/receipts/`: a receipt for every birthday cake, paid or canceled.
- `answers.txt`: four questions, each with a numbered line for your answer.
- `check.bats`: the check. You don't need to change it.

## What to do

Open a terminal, `cd` into the exercise folder (the one with `answers.txt` in it), then `cd bakery` and look at the start of the orders with `head -n 3 orders.csv`. Then work through the list, from inside `bakery`:

1. **Answer the four questions** in `answers.txt`, each with a pipeline. Open it in nano (`nano ../answers.txt` from inside `bakery`), write each answer after its `)`, and save. The file starts like this:

```text
# Example: what is the name of the first column in bakery/orders.csv?
# 0) order

# 1. How many orders does bakery/orders.csv hold? Don't count the header line.
1)
```

2. **Rank the cities.** Make `city-report.txt`: one line per city, its number of orders first, the most orders at the top. Save it with `tee`, so you see the ranking as you save it (*Tee and Xargs: Splitting and Feeding*).
3. **Make a mailing list.** Make `mailing-list.txt`: every customer's email address once, in lowercase, one a line (*Columns and Characters: cut and tr*).
4. **Keep two logs.** Bea's notes say there's a `refunds.csv` as well. Count the lines of `orders.csv` and `refunds.csv` with one `wc -l`, sending the counts into `counts.txt` and the errors into `errors.txt` (*Three Streams: Output, Errors and Input*).
5. **Delete the canceled receipts.** Remove every receipt in `receipts` that says `CANCELED`, and keep every one that says `PAID`. Look before you delete.

## Check your work

From the exercise folder (not from inside `bakery`):

```bash
bats check.bats
```

At first most checks fail. That's expected: each job you finish turns its check into a ✓. A failing check names the job and gives a hint, for example *mailing-list.txt still has capital letters in it. Put tr 'A-Z' 'a-z' in the pipeline before sort -u.*

## Hints

- **Build a pipeline a stage at a time.** Run the first command with `| head -n 5` on the end, look at what it hands on, then add the next stage.
- **The header line isn't an order.** `wc -l` counts it too, and `cut` keeps it. `tail -n +2` starts from the second line.
- **Ranking anything** is `sort | uniq -c | sort -rn`, as in *Count, Sort, Remove Duplicates: wc, sort and uniq*. Without the first `sort`, the counts come out in small pieces.
- **Capitals count as different letters** to `sort -u`, so make the emails lowercase first. `tr` takes no file name: feed it with a pipe.
- **One arrow for results, `2>` for errors.** `&>` and `2>&1` would put both in the same file.
- **`rm` has no undo.** `grep -l CANCELED receipts/*` lists the files; `| xargs echo rm` shows the command; only then `| xargs rm`.

## When you're done

Every check passes:

```text
check.bats
 ✓ the bakery folder is still here
 ✓ 1) how many orders there are
 ✓ 2) how many cinnamon roll orders
 ✓ 3) the item ordered most often
 ✓ 4) how many different customers
 ✓ city-report.txt ranks the cities, most orders first
 ✓ mailing-list.txt has every customer's email once, in lowercase
 ✓ counts.txt holds the counts and errors.txt the error
 ✓ the canceled receipts are gone
 ✓ every paid cake receipt is still there

10 tests, 0 failures
```

Now look back at your ranking of the cities. Which column would you cut to rank the months instead, and what would you add so the dates group by month? (*Columns and Characters: cut and tr* shows one way.)

## Submit your exercise

The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.

1. On GitHub, click **+**, then **New repository**. Name it (for example `exercise-bash-the-bakerys-orders`), choose **Public**, and click **Create repository**. Leave out the README: your folder already has one.
2. In a terminal in your exercise folder (Ubuntu in WSL on Windows), send your work to your new repo. If you downloaded the ZIP:

   ```bash
   git init -b main
   git add .
   git commit -m "My solution"
   git remote add origin https://github.com/your-name/exercise-bash-the-bakerys-orders.git
   git push -u origin main
   ```

   If you cloned the starter instead, point your copy at your own repo, then commit and push:

   ```bash
   git remote set-url origin https://github.com/your-name/exercise-bash-the-bakerys-orders.git
   git add .
   git commit -m "My solution"
   git push -u origin main
   ```

3. Paste your repo's address, such as `https://github.com/your-name/exercise-bash-the-bakerys-orders`, into **Submit your exercise** on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.

Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.

## So what

Counting, ranking, cleaning a column, keeping logs and acting on exactly what a search found: these pipelines are the everyday work of anyone who answers questions from data, from a bakery's owner to a data analyst or the person who looks after a website's server.

## Key terms

- [Pipe](https://www.ask-codey.com/glossary/pipe-unix)
- [Redirection](https://www.ask-codey.com/glossary/redirection)
- [sort and uniq](https://www.ask-codey.com/glossary/sort-and-uniq)
- [cut](https://www.ask-codey.com/glossary/cut)
- [xargs](https://www.ask-codey.com/glossary/xargs)

## Related

- [Pipes: |](https://www.ask-codey.com/lessons/bash-pipes)
- [Three Streams: Output, Errors and Input](https://www.ask-codey.com/lessons/bash-streams-and-redirection)
- [Count, Sort, Remove Duplicates: wc, sort and uniq](https://www.ask-codey.com/lessons/bash-count-sort-unique)
- [Columns and Characters: cut and tr](https://www.ask-codey.com/lessons/bash-cut-and-tr)
- [Tee and Xargs: Splitting and Feeding](https://www.ask-codey.com/lessons/bash-tee-and-xargs)

Source: https://www.ask-codey.com/lessons/exercise-bash-the-bakerys-orders
