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.
findutility not get concerned of such tricky behaviorreaddirhas essentially the same specification. I would expect it to be potentially filesystem-specific, even (loading one block of directory entries at a time is pretty reasonable).findutility don't get concerned with the behavior. It means it's left to the authors of any given implementation of thefindutility how to handle that case, rather than being specified. (If that seems unclear I recommend you fully clear up the words "specification" and "implementation" as they apply to software.)finddevs don't mention it). As described in ikkachu's answer, that's a filesystem level behavior, not even specified in thereaddir()system call spec. There are going to be race conditions no matter what.