Those patches look good to me.  Here are two follow-ups.

The first updates the docs to mention the equal-timestamps pitfall.   The
second tweaks some of the shell code examples (quoting, among other things).
From 79c38669d1bff076a7f2bc567addc88093725b3e Mon Sep 17 00:00:00 2001
From: James Youngman <[email protected]>
Date: Tue, 14 Oct 2025 19:50:29 +0100
Subject: [PATCH 1/2] find: point out that -newer is false when timestamps are
 equal.

---
 doc/find.texi | 15 ++++++++++-----
 find/find.1   | 14 ++++++++++++--
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/doc/find.texi b/doc/find.texi
index 3d7c63a1..0892f3d6 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -1036,8 +1036,9 @@ command line.
 
 @deffn Test -newerXY reference
 Succeeds if timestamp @samp{X} of the file being considered is newer
-than timestamp @samp{Y} of the file @file{reference}.   The letters
-@samp{X} and @samp{Y} can be any of the following letters:
+than timestamp @samp{Y} of the file @file{reference}.
+Fails if the timestamps are @emph{equal}.
+The letters @samp{X} and @samp{Y} can be any of the following letters:
 
 @table @samp
 @item a
@@ -1077,7 +1078,8 @@ not UFS1 file systems.
 
 
 There are two ways to list files in @file{/usr} modified after
-February 1 of the current year.  One uses @samp{-newermt}:
+@emph{the start} of February 1 of the current year.  One uses
+@samp{-newermt}:
 
 @example
 find /usr -newermt "Feb 1"
@@ -1098,6 +1100,7 @@ rm -f /tmp/stamp$$
 True if the time of the last access (or status change or data modification)
 of the current file is more recent than that of the last data modification
 of the @var{reference} file.
+False if the timestamps are equal.
 As such, @samp{-anewer} is equivalent to @samp{-neweram},
 @samp{-cnewer} to @samp{-newercm}, and @samp{-newer} to @samp{-newermm}.
 
@@ -5059,7 +5062,8 @@ find subdir -newer timestamp -and \
 @end smallexample
 
 Here, the @samp{-newer} test excludes all the files which are
-definitely older than the timestamp, but all the files which are newer
+definitely older than or the same age as
+the timestamp, but all the files which are newer
 than the old value of the timestamp are compared against the current
 updated timestamp.
 
@@ -5132,7 +5136,8 @@ find subdir -newer timestamp -printf "%A@@:%p\0" |
 @end smallexample
 
 The first @code{find} command generates a list of files which are
-newer than the original timestamp file, and prints a list of them with
+newer than (and not the same age as) the original timestamp file,
+and prints a list of them with
 their timestamps.  The @file{newest.pl} script simply filters out all
 the filenames which have timestamps which are older than whatever the
 newest file is:
diff --git a/find/find.1 b/find/find.1
index 27c3316b..a51a2f4b 100644
--- a/find/find.1
+++ b/find/find.1
@@ -716,6 +716,8 @@ Like
 .BR \-newer ,
 but test if the time of the last access of the current file is more recent than
 that of the last data modification of the \fIreference\fR file.
+Fails if the timestamps are
+.BR equal .
 If \fIreference\fR is a symbolic link and the
 .B \-H
 option or the
@@ -745,6 +747,8 @@ Like
 .BR \-newer ,
 but test if the time of the last status change of the current file is more
 recent than that of the last data modification of the \fIreference\fR file.
+Fails if the timestamps are
+.BR equal .
 If \fIreference\fR is a symbolic link and the
 .B \-H
 option or the
@@ -905,8 +909,11 @@ Don't forget to enclose the pattern in quotes in order to protect it
 from expansion by the shell.
 
 .IP "\-newer \fIreference\fR"
-Time of the last data modification of the current file is more recent than that
+Succeeds if the
+time of the last data modification of the current file is more recent than that
 of the last data modification of the \fIreference\fR file.
+Fails if the timestamps are
+.BR equal .
 If \fIreference\fR is a symbolic link and the
 .B \-H
 option or the
@@ -916,8 +923,11 @@ it points to is always used.
 
 .IP "\-newerXY \fIreference\fR"
 Succeeds if timestamp \fIX\fR of the file being considered is newer
-than timestamp \fIY\fR of the file
+than
+the timestamp \fIY\fR of the file
 .IR reference .
+Fails if the timestamps are
+.BR equal .
 The letters \fIX\fR and \fIY\fR can be any of the following letters:
 
 .TS
-- 
2.39.5

From 87a34fa37070bb95e235145f958dbdefe5232f3c Mon Sep 17 00:00:00 2001
From: James Youngman <[email protected]>
Date: Tue, 14 Oct 2025 20:17:12 +0100
Subject: [PATCH 2/2] doc: minor shell coding improvements in examples.

- Use -type f so that the timestamp of `subdir` is not relevant.
- Use LC_ALL=C with sort, tail, cut (as file names are not text).
- Use "$(...)" instead of just $(...).

Also mention that Issue 8 of the POSIX standard has been published
now.
---
 doc/find.texi | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/doc/find.texi b/doc/find.texi
index 0892f3d6..581807d7 100644
--- a/doc/find.texi
+++ b/doc/find.texi
@@ -4680,6 +4680,9 @@ there are lots of files to delete.  Since the task is to delete
 unwanted files, this is precisely the time we don't want things to go
 wrong.
 
+There is also a second problem with this method.  We will discuss that
+below.
+
 @subsection Making Use of @code{xargs}
 
 So, is there a way to be more efficient in the use of @code{fork()}
@@ -4753,8 +4756,7 @@ portable construct.  Support for @samp{-print0} is not universal.
 
 Although some other versions of Unix (notably BSD-derived ones)
 support @samp{-print0}, this is only required in POSIX from Issue 8
-(which as of 2024-06-03 has not yet been published). So, is there a
-more universal mechanism?
+(published 2024-06-14). So, is there a more universal mechanism?
 
 @subsection Going back to @code{-exec}
 
@@ -5021,7 +5023,7 @@ different ways to do it.
 The obvious but wrong answer is just to use @samp{-newer}:
 
 @smallexample
-find subdir -newer timestamp -exec touch -r @{@} timestamp \;
+find subdir -type f -newer timestamp -exec touch -r @{@} timestamp \;
 @end smallexample
 
 This does the right sort of thing but has a bug.  Suppose that two
@@ -5042,7 +5044,7 @@ compared against it, but that will reduce the performance of
 The @code{test} command can be used to compare timestamps:
 
 @smallexample
-find subdir -exec test @{@} -nt timestamp \; -exec touch -r @{@} timestamp \;
+find subdir -type f -exec test @{@} -nt timestamp \; -exec touch -r @{@} timestamp \;
 @end smallexample
 
 This will ensure that any changes made to the modification time of
@@ -5056,7 +5058,7 @@ We can of course still use @samp{-newer} to cut down on the number of
 calls to @code{test}:
 
 @smallexample
-find subdir -newer timestamp -and \
+find subdir -type f -newer timestamp -and \
      -exec test @{@} -nt timestamp \; -and \
      -exec touch -r @{@} timestamp \;
 @end smallexample
@@ -5076,10 +5078,8 @@ It is possible to use the @samp{-printf} action to abandon the use of
 @code{test} entirely:
 
 @smallexample
-newest=$(find subdir -newer timestamp -printf "%A@@:%p\n" |
-           sort -n |
-           tail -n1 |
-           cut -d: -f2- )
+newest="$(find subdir -type f -newer timestamp -printf "%A@@:%p\n" |
+           env LC_ALL=C sh -c 'sort -n | tail -n1 | cut -d: -f2-' )"
 touch -r "$@{newest:-timestamp@}" timestamp
 @end smallexample
 
@@ -5087,19 +5087,20 @@ The command above works by generating a list of the timestamps and
 names of all the files which are newer than the timestamp.  The
 @code{sort}, @code{tail} and @code{cut} commands simply pull out the
 name of the file with the largest timestamp value (that is, the latest
-file).  The @code{touch} command is then used to update the timestamp,
+file).  We run those programs (which normally read and write text)
+with with the @env{LC_ALL} environment variable set to @samp{C} in
+order to avoid character encoding problems; file names are not
+guaranteed to have a valid (or consistent) character encoding.  The
+@code{touch} command is then used to update the timestamp,
 
 The @code{"$@{newest:-timestamp@}"} expression simply expands to the
 value of @code{$newest} if that variable is set, but to
 @file{timestamp} otherwise.  This ensures that an argument is always
 given to the @samp{-r} option of the @code{touch} command.
 
-This approach seems quite efficient, but unfortunately it has a
-problem.  Many operating systems now keep file modification time
-information at a granularity which is finer than one second.
-Findutils version 4.3.3 and later will print a fractional part with
-%A@@, but older versions will not.
-
+@c We used to warn the reader about older versions of Find where %A@
+@c didn't include a fractional part, but since Findutils 4.3.3 was
+@c released in 2007, people are unlikely to have a problem today.
 
 @subsection Solving the problem with @code{make}
 
@@ -5108,8 +5109,9 @@ use @code{find} to generate a @file{Makefile} file on the fly and then
 use @code{make} to update the timestamps:
 
 @smallexample
-makefile=$(mktemp)
+makefile="$(mktemp)"
 find subdir \
+        -type f \
         \( \! -xtype l \) \
         -newer timestamp \
         -printf "timestamp:: %p\n\ttouch -r %p timestamp\n\n" > "$makefile"
@@ -5129,7 +5131,7 @@ space), and do things more efficiently too.  The following command
 works with newlines and doesn't need to sort the list of filenames.
 
 @smallexample
-find subdir -newer timestamp -printf "%A@@:%p\0" |
+find subdir -type f -newer timestamp -printf "%A@@:%p\0" |
    perl -0 newest.pl |
    xargs --no-run-if-empty --null --replace \
       find @{@} -maxdepth 0 -newer timestamp -exec touch -r @{@} timestamp \;
-- 
2.39.5

Reply via email to