Comparing the time of a symlink

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












5















I want to check whether link lnkfile is older than a regular reference file reffile.



The bash test builtin dereferences links, so test lnkfile -ot reffile compares the target of lnkfile, not the link itself.



Is there a way to make the test builtin not follow symlinks? Otherwise, how can I compare the time of a symlink?










share|improve this question




























    5















    I want to check whether link lnkfile is older than a regular reference file reffile.



    The bash test builtin dereferences links, so test lnkfile -ot reffile compares the target of lnkfile, not the link itself.



    Is there a way to make the test builtin not follow symlinks? Otherwise, how can I compare the time of a symlink?










    share|improve this question


























      5












      5








      5








      I want to check whether link lnkfile is older than a regular reference file reffile.



      The bash test builtin dereferences links, so test lnkfile -ot reffile compares the target of lnkfile, not the link itself.



      Is there a way to make the test builtin not follow symlinks? Otherwise, how can I compare the time of a symlink?










      share|improve this question
















      I want to check whether link lnkfile is older than a regular reference file reffile.



      The bash test builtin dereferences links, so test lnkfile -ot reffile compares the target of lnkfile, not the link itself.



      Is there a way to make the test builtin not follow symlinks? Otherwise, how can I compare the time of a symlink?







      bash shell-script symlink timestamps






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 21 at 23:12









      Jeff Schaller

      41.1k1056131




      41.1k1056131










      asked Jan 21 at 22:02









      L. LevrelL. Levrel

      1,322413




      1,322413




















          3 Answers
          3






          active

          oldest

          votes


















          2














          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.







          share|improve this answer

























          • What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

            – Kusalananda
            Jan 21 at 22:50












          • @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

            – Sparhawk
            Jan 21 at 22:56












          • I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

            – Kusalananda
            Jan 22 at 0:13






          • 1





            @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

            – Sparhawk
            Jan 22 at 1:25






          • 1





            Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

            – L. Levrel
            Jan 22 at 13:21


















          3














          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





          share|improve this answer























          • Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

            – L. Levrel
            Jan 22 at 8:50


















          1














          With zsh 5.6 or above (for the nanosecond precision), you could do it with builtins only with:



          zmodload zsh/stat
          if
          stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
          stat -A reftime -F '%021s%N' +mtime -- $reffile &&
          [[ $lnktime < $reftime ]]
          then
          print -r -- $lnkfile is older than $reffile
          fi


          Which would work regardless of what characters or non-characters the file names contain and compare timestamps down to the nanosecond.



          We're comparing the timestamps as strings (number of nanoseconds as a decimal string representation zero-padded to 30 digits) instead of floating points because the typical double precision floating points of a x86_64 PC running GNU/Linux at least don't have enough precision to store numbers like 1548195897.775033155 so you would not be able to tell apart two files modified today within the same 100 nanoseconds.



          $ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
          $ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
          yes





          share|improve this answer

























          • Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

            – L. Levrel
            Jan 23 at 10:00










          Your Answer








          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "106"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f495864%2fcomparing-the-time-of-a-symlink%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          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.







          share|improve this answer

























          • What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

            – Kusalananda
            Jan 21 at 22:50












          • @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

            – Sparhawk
            Jan 21 at 22:56












          • I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

            – Kusalananda
            Jan 22 at 0:13






          • 1





            @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

            – Sparhawk
            Jan 22 at 1:25






          • 1





            Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

            – L. Levrel
            Jan 22 at 13:21















          2














          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.







          share|improve this answer

























          • What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

            – Kusalananda
            Jan 21 at 22:50












          • @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

            – Sparhawk
            Jan 21 at 22:56












          • I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

            – Kusalananda
            Jan 22 at 0:13






          • 1





            @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

            – Sparhawk
            Jan 22 at 1:25






          • 1





            Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

            – L. Levrel
            Jan 22 at 13:21













          2












          2








          2







          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.







          share|improve this answer















          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.








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 22 at 23:28

























          answered Jan 21 at 22:15









          SparhawkSparhawk

          9,59864093




          9,59864093












          • What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

            – Kusalananda
            Jan 21 at 22:50












          • @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

            – Sparhawk
            Jan 21 at 22:56












          • I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

            – Kusalananda
            Jan 22 at 0:13






          • 1





            @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

            – Sparhawk
            Jan 22 at 1:25






          • 1





            Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

            – L. Levrel
            Jan 22 at 13:21

















          • What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

            – Kusalananda
            Jan 21 at 22:50












          • @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

            – Sparhawk
            Jan 21 at 22:56












          • I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

            – Kusalananda
            Jan 22 at 0:13






          • 1





            @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

            – Sparhawk
            Jan 22 at 1:25






          • 1





            Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

            – L. Levrel
            Jan 22 at 13:21
















          What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

          – Kusalananda
          Jan 21 at 22:50






          What test implementation do you have that does not have -n? It's a standard option... Also quote the command substitution.

          – Kusalananda
          Jan 21 at 22:50














          @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

          – Sparhawk
          Jan 21 at 22:56






          @Kusalananda I'm just confirming that no options is identical to -n, so it's easier to grep the man. Good point with the quote. Thanks.

          – Sparhawk
          Jan 21 at 22:56














          I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

          – Kusalananda
          Jan 22 at 0:13





          I misunderstood what you were saying about -n and read it as "there is no -n option" instead of "test without an option is the same as test -n".

          – Kusalananda
          Jan 22 at 0:13




          1




          1





          @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

          – Sparhawk
          Jan 22 at 1:25





          @Kusalananda Ah got it. I edited to clarify my ambiguous language. Thanks again.

          – Sparhawk
          Jan 22 at 1:25




          1




          1





          Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

          – L. Levrel
          Jan 22 at 13:21





          Thank you, I'm convinced. It's striking to see how the process calls dominate the total overhead of these loops!

          – L. Levrel
          Jan 22 at 13:21













          3














          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





          share|improve this answer























          • Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

            – L. Levrel
            Jan 22 at 8:50















          3














          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





          share|improve this answer























          • Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

            – L. Levrel
            Jan 22 at 8:50













          3












          3








          3







          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





          share|improve this answer













          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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 21 at 22:08









          Chris DownChris Down

          80.2k14189202




          80.2k14189202












          • Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

            – L. Levrel
            Jan 22 at 8:50

















          • Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

            – L. Levrel
            Jan 22 at 8:50
















          Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

          – L. Levrel
          Jan 22 at 8:50





          Thank you for answering. Now I'm well embarrassed with two valid answers: what do you think about Sparhawk's solution? Especially in re efficiency, since I'll have scores of link-and-file pairs to test.

          – L. Levrel
          Jan 22 at 8:50











          1














          With zsh 5.6 or above (for the nanosecond precision), you could do it with builtins only with:



          zmodload zsh/stat
          if
          stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
          stat -A reftime -F '%021s%N' +mtime -- $reffile &&
          [[ $lnktime < $reftime ]]
          then
          print -r -- $lnkfile is older than $reffile
          fi


          Which would work regardless of what characters or non-characters the file names contain and compare timestamps down to the nanosecond.



          We're comparing the timestamps as strings (number of nanoseconds as a decimal string representation zero-padded to 30 digits) instead of floating points because the typical double precision floating points of a x86_64 PC running GNU/Linux at least don't have enough precision to store numbers like 1548195897.775033155 so you would not be able to tell apart two files modified today within the same 100 nanoseconds.



          $ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
          $ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
          yes





          share|improve this answer

























          • Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

            – L. Levrel
            Jan 23 at 10:00















          1














          With zsh 5.6 or above (for the nanosecond precision), you could do it with builtins only with:



          zmodload zsh/stat
          if
          stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
          stat -A reftime -F '%021s%N' +mtime -- $reffile &&
          [[ $lnktime < $reftime ]]
          then
          print -r -- $lnkfile is older than $reffile
          fi


          Which would work regardless of what characters or non-characters the file names contain and compare timestamps down to the nanosecond.



          We're comparing the timestamps as strings (number of nanoseconds as a decimal string representation zero-padded to 30 digits) instead of floating points because the typical double precision floating points of a x86_64 PC running GNU/Linux at least don't have enough precision to store numbers like 1548195897.775033155 so you would not be able to tell apart two files modified today within the same 100 nanoseconds.



          $ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
          $ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
          yes





          share|improve this answer

























          • Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

            – L. Levrel
            Jan 23 at 10:00













          1












          1








          1







          With zsh 5.6 or above (for the nanosecond precision), you could do it with builtins only with:



          zmodload zsh/stat
          if
          stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
          stat -A reftime -F '%021s%N' +mtime -- $reffile &&
          [[ $lnktime < $reftime ]]
          then
          print -r -- $lnkfile is older than $reffile
          fi


          Which would work regardless of what characters or non-characters the file names contain and compare timestamps down to the nanosecond.



          We're comparing the timestamps as strings (number of nanoseconds as a decimal string representation zero-padded to 30 digits) instead of floating points because the typical double precision floating points of a x86_64 PC running GNU/Linux at least don't have enough precision to store numbers like 1548195897.775033155 so you would not be able to tell apart two files modified today within the same 100 nanoseconds.



          $ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
          $ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
          yes





          share|improve this answer















          With zsh 5.6 or above (for the nanosecond precision), you could do it with builtins only with:



          zmodload zsh/stat
          if
          stat -LA lnktime -F '%021s%N' +mtime -- $lnkfile &&
          stat -A reftime -F '%021s%N' +mtime -- $reffile &&
          [[ $lnktime < $reftime ]]
          then
          print -r -- $lnkfile is older than $reffile
          fi


          Which would work regardless of what characters or non-characters the file names contain and compare timestamps down to the nanosecond.



          We're comparing the timestamps as strings (number of nanoseconds as a decimal string representation zero-padded to 30 digits) instead of floating points because the typical double precision floating points of a x86_64 PC running GNU/Linux at least don't have enough precision to store numbers like 1548195897.775033155 so you would not be able to tell apart two files modified today within the same 100 nanoseconds.



          $ ((1548195897.775033155 < 1548195897.775033255)) && echo yes
          $ [[ 1548195897775033155 < 1548195897775033255 ]] && echo yes
          yes






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 23 at 10:50

























          answered Jan 22 at 22:31









          Stéphane ChazelasStéphane Chazelas

          305k57574927




          305k57574927












          • Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

            – L. Levrel
            Jan 23 at 10:00

















          • Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

            – L. Levrel
            Jan 23 at 10:00
















          Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

          – L. Levrel
          Jan 23 at 10:00





          Thank you for the details. Could you expand about "non-characters" please? I've tested with a filename containing newline: GNU stat shows no problem. find will replace the newline with ? if output goes to the terminal, otherwise it is preserved (which is the case in Sparhawk's answer, but anyway we're just testing if there's any output, so ? would be fine). All substitutions are double-quoted to avoid word splitting.

          – L. Levrel
          Jan 23 at 10:00

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Unix & Linux Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f495864%2fcomparing-the-time-of-a-symlink%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown






          Popular posts from this blog

          How to check contact read email or not when send email to Individual?

          Displaying single band from multi-band raster using QGIS

          How many registers does an x86_64 CPU actually have?