Linux – Find Command Picking Files of Unrelated Pattern

bashcommand linefindlinux

I have a following find command which I trigger via autosys scheduler. The command is used to delete file older than X days.

find /home/my_home/document -maxdepth 1 -type f -mtime +31 -name "qwer_*" -delete -print

But above command fails is failing.
Weird part is, in logs I can see find is picking up the files which does not even match the qwer_* pattern

eg.

find: `/home/my_home/document/yumn.txt': No such file or directory
find: `/home/my_home/document/ztry.txt': No such file or directory

Am I missing anything in find command.

Best Answer

In your previous question you said:

I suspect it is due to some other parallel job is deleting some of the files.

This is exactly what happened in this case. Your find found out there's a file yumn.txt, then the file was deleted, then find tried to do something with the file and failed. The same scenario for ztry.txt.

Note it doesn't mean that if yumn.txt was not simultaneously deleted, then find would delete and print it. It only means yumn.txt unexpectedly disappeared before find was done testing it.


You may expect -name "qwer_*" to reject yumn.txt according to sole directory listing (from which find learns about the existence of the file in the first place), so the tool never needs to query about the file itself (later, when the file doesn't exist). My tests indicate this is not always the case.

In general find may or may not rearrange tests. This means -name "qwer_*" may be tested before or after -mtime +31 etc. E.g. GNU find reorders expressions so that tests based only on the names of files are performed early. See man 1 find, -O and -D options. But in your case maybe what you typed first was tested first, so yumn.txt was meant to be tested against -type f and -mtime +31, and at least one of these tests required the file to exist at the moment the test was performed.

But even with sole find . -name "qwer_*" it's possible to encounter the problem. I tested like this:

while true; do touch yumn.txt; rm yumn.txt; done &

Then ls yumn.txt would find a file or not. You can repeat ls yumn.txt many times and sometimes you will find a file, sometimes not. This is expected.

In my Debian, when yumn.txt keeps being created and destroyed on a Btrfs filesystem, find . -name "qwer_*" doesn't complain about it; or at least it did not when I tested repeatedly more than 4k times.

On the other hand in my OpenWRT router find . -name "qwer_*" sometimes does complain, and the message is almost exactly like yours:

find: ./yumn.txt: No such file or directory

It's find from BusyBox and the filesystem is overlayfs (with ext3 as the upperdir). The conclusion is: in some circumstances it's possible that a file being deleted by another process makes find complain (and return non-zero exit status!), even if -name could in theory reject the file in the first place.


Not a general solution, but in your specific case you can try this approach:

find /home/my_home/document/qwer_* -maxdepth 0 -type f -mtime +31 -delete -print

Now the shell performs pattern matching and runs find with only matching files as starting points. Because of -maxdepth 0 find examines only the given files (relevant if at least one of them happens to be a directory). This way disappearing yumn.txt or such cannot affect find. Possible problems:

  • If qwer_* files are deleted by other process(es) (like yumn.txt was), it may happen find complains and returns non-zero exit status.
  • If there are too many qwer_* files then you will get Argument list too long (or similar).
  • If there is no match at all, find will get literal /home/my_home/document/qwer_* starting point and complain about nonexisting file/directory.
Related Question