October 5, 2026 路 #19
The loop that split on spaces
This cleanup walks a directory of uploaded files. What breaks on a real filename?
#!/usr/bin/env bash
set -euo pipefail
for file in $(ls /data/uploads); do
echo "archiving $file"
gzip "/data/uploads/$file"
doneNext puzzle in UTC
One try. The first answer sticks.
How to fix it
Command substitution splits on IFS. A file named report 2026.pdf becomes two iterations, and both gzip paths are wrong. Iterate a glob instead of ls.
$(ls /data/uploads) is a string. The for loop splits that string on spaces, tabs, and newlines. report 2026.pdf becomes report and 2026.pdf. gzip then runs on two paths that do not exist, or worse, on a different file that happens to match one of the pieces. ls also exits 0 when the directory is empty on some platforms and non-zero on others, so set -e behavior depends on who wrote coreutils.
A glob does not split names. The shell hands each filename to the loop as one word.
Fix
shopt -s nullglob
for file in /data/uploads/*; do
gzip -- "$file"
done
nullglob makes an empty directory skip the loop instead of running once on the literal string *. For a recursive walk, use find /data/uploads -type f -print0 | while IFS= read -r -d '' file; do ...; done.