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 thestat
one needs the GNU implementation ofstat
. Thestat
one won't work for files modified within the same second (whilefind
should work on systems where sub-second granularity for timestamps is supported). Neitherfind
norstat
support arbitrary file names.You'll find other differences if either of the files cannot be
stat()
ed.