Fix a script that breaks on spaces OPS-2251

OpenShell basics · Easy · Do · about 15 min ·Linux

Lab machine

A private Linux machine with the problem already set up. Sessions last up to 60 minutes.
Ana Costa opened OPS-2251 at 13:05task

The weekly package report says West Dock 2 handled 999 parcels. It handled 66. The script reads three files that are not the one you asked for.

bin/count-packages prints the parcel total for each export file it is given. Depot exports are named after the dock, spaces and all. Renaming them is not an option: the warehouse system writes them with those names every night.

"Can you make the script work with the real file names? The managers read this report every Friday." (Ana)

When a shell expands a variable without quotes, it splits the result on spaces and expands any * or ? in it. srv/exports/ also happens to contain files called West and 2.csv.

Your task

Fix bin/count-packages so each argument is treated as one file name, whatever it contains, then confirm bin/count-packages "srv/exports/West Dock 2.csv" prints a single, correct total. Do not rename or edit the exports.

On the machine

  • bin/count-packages
  • srv/exports/ with West Dock 2.csv, North Gate (cold).csv, and two decoys
  • bash -x shows the words the shell really passes

Timeline

Fri 17:00Weekly report goes to depot managers: West Dock 2, 999 parcels.
13:00The West Dock 2 manager calls Ana: "We did not do 999."
13:05Ana opens OPS-2251.

Done when

  1. bin/count-packages "srv/exports/West Dock 2.csv" prints one correct total.
  2. It also works for names with double spaces and wildcard characters.
  3. The export files keep their names and contents.

Hints

Hint 1

Run the command from the ticket and read which files it tried to open.

Hint 2

Without quotes, the shell splits a variable on spaces and expands * and ?.

Hint 3

Quote every expansion: "$@" and "$file".

Hint 4

bash -x bin/count-packages "srv/exports/West Dock 2.csv" shows each word the shell passes.

Show the solution

Change for file in $@ to for file in "$@", and tail -n +2 $file to tail -n +2 "$file".