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

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:

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, 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:
# 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)
  1. 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).
  2. 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).
  3. 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).
  4. 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):

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:

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:

    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:

    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

Related