Performing -nt/-ot test in a POSIX sh
POSIXLY:
f1=/path/to/file_1
f2=/path/to/file_2
if [ -n "$(find -L "$f1" -prune -newer "$f2")" ]; then
printf '%s is newer than %s\n' "$f1" "$f2"
fi
Using absolute path to files prevent a false positive with filename contains newlines only.
In case of using relative path, then change find
command to:
find -L "$f1" -prune -newer "$f2" -exec echo . \;
This could be a case for using one of the oldest Unix command, ls
.
x=$(ls -tdL -- "$a" "$b")
[ "$x" = "$a
$b" ]
The result is true if a is newer than b.
You raised an interesting question and made a claim that should first be verified.
I checked the behavior of:
$shell -c '[ Makefile -nt SCCS/s.Makefile ] && echo newer'
with various shells. Here are the results:
bash Does not work - prints nothing.
bosh works
dash Does not work - prints nothing.
ksh88 Does not work - prints nothing.
ksh93 works
mksh Does not work - prints nothing.
posh prints: posh: [: -nt: unexpected operator/operand
yash works
zsh works in newer versions, older versions print nothing
So four of nine shells support the -nt feature and implement it correctly. Correctly in this case means: is able to compare time stamps on recent platforms that support sub-second time stamp granularity. Note that the files I selected differ typically only a few microseconds in their time stamps.
Since it is easier to find a working find
implementation, I recommend to replace
if [ "$file1" -nt "$file2" ] ; then
echo newer
fi
by a find
based expression.
if [ "$( find "$file1" -newer "$file2" )" ]; then
echo newer
fi
works at least as long as $file1
does not only contain newlines.
if [ "$( find -L "$file1" -newer "$file2" -exec echo newer \; )" ]; then
echo newer
fi
is a bit slower but works correctly.
BTW: Regarding make I cannot speak for all make implementations, but SunPro Make
supports time comparison with nanosecond granularity since approx. 20 years, while smake
and gmake
added this feature recently.