3 SC2202
Joachim Ansorg edited this page 2021-11-12 19:48:21 +01:00

Globs don't work as operands in [ ]. Use a loop.

Problematic code:

[ current.log -nt backup/*.log ] && echo "This is the latest file"

Correct code:

newerThanAll=true
for log in backup/*.log
do
  [ current.log -nt "$log" ] || newerThanAll=false
done
[ "$newerThanAll" = "true" ] && echo "This is the latest file"

Rationale:

Globs in [ ] will expand to a sequence of words, one per matching filename. Meanwhile, operators work on single words.

The problematic code is equivalent to [ current.log -nt backup/file1.log backup/file2.log backup/file3.log ], which is invalid syntax. A typical error message is bash: [: too many arguments or dash: somefile: unexpected operator.

Instead, use a for loop to iterate over matching filenames, and apply your condition to each.

Exceptions:

If you know your glob will only ever match one file, you can check this explicitly and use the first file:

set -- backup/*.log
[ $# -eq 1 ] || { echo "There are too many matches."; exit 1; }
[ file.log -nt "$1" ] && echo "This is the latest file"

Alternatively, ignore this warning.