Comparing the time of a symlink

As far as I know, bash doesn't offer any versions of -ot (and the like) which avoid dereferencing symlinks.

What you can do instead is use GNU stat (which doesn't dereference symbolic links without -L) and compare their mtime epochs numerically:

if (( "$(stat --format=%Z lnkfile)" < "$(stat --format=%Z reffile)" )); then
    # lnkfile is older
fi

I don't think there is a way with test, but you could use find.

test "$(find reffile -prune -newer lnkfile)" && command

Here, find returns output if lnkfile is older than reffile. test without an option is equivalent to test -n. This is true if the length of the string is nonzero. Hence, if there is output from find, command is executed.


In the comments, I was asked to make a comparison of this solution vs. stat. Firstly, I find the stat approach perfectly fine.

I did a benchmark to compare. I repeated the test a few times, alternating, and got similar results.

$ time (for i in {1..1000}; do test "$(stat --format=%Z a)" -lt "$(stat --format=%Z b)" && echo foo > /dev/null ; done)

================
CPU 101%
CPU 104%
user    1.264
system  0.942
total   2.108

$ time (for i in {1..1000}; do test "$(find b -newer a)" && echo foo > /dev/null ; done)

================
CPU 104%
user    0.693
system  0.526
total   1.164

I looks like find is almost twice as fast, perhaps because it's a single process rather than two stats? I'm not sure how else to compare them; please comment if there are other relevant aspects you can think of.

Here are some other differences, as per Stéphane Chazelas's comments below:

Other differences are: the find one is standard. while the stat one needs the GNU implementation of stat. The stat one won't work for files modified within the same second (while find should work on systems where sub-second granularity for timestamps is supported). Neither find nor stat support arbitrary file names.

You'll find other differences if either of the files cannot be stat()ed.