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.