While answering an older question it struck me that it seems find, in the following example, potentially would process files multiple times:
find dir -type f -name '*.txt' \
-exec sh -c 'mv "$1" "${1%.txt}_hello.txt"' sh {} ';'
or the more efficient
find dir -type f -name '*.txt' \
-exec sh -c 'for n; do mv "$n" "${n%.txt}_hello.txt"; done' sh {} +
The command finds .txt files and changes their filename suffix from .txt to _hello.txt.
While doing so, the directories will start accumulating new files whose names matches the *.txt pattern, namely these _hello.txt files.
Question: Why are they not actually processed by find? Because in my experience they aren't, and we don't want them to be either as it would introduce a sort of infinite loop. This is also the case with mv replaced by cp, by the way.
The POSIX standard says (my emphasis)
If a file is removed from or added to the directory hierarchy being searched it is unspecified whether or not
findincludes that file in its search.
Since it's unspecified whether new files will be included, maybe a safer approach would be
find dir -type d -exec sh -c '
for n in "$1"/*.txt; do
test -f "$n" && mv "$n" "${n%.txt}_hello.txt"
done' sh {} ';'
Here, we don't look for files but for directories, and the for loop of the internal sh script evaluates its range once before the first iteration, so we don't have the same potential issue.
The GNU find manual does not explicitly say anything about this and neither does the OpenBSD find manual.