0

I have a script that deletes files older than N minutes. The script basically runs:

find /some-folder/* -mmin +59 | xargs rm -rf

But for some reason it prints tons of: No such file or directory but seems to do the work, e.g. see below example:

$ du -hs /opt/storage/
5.2G    /opt/storage/
$ find /opt/storage/* -mmin +59 | xargs rm -rf
find: /opt/storage/caches/modules-2/files-2.1/org.jboss/jboss-parent: No such file or directory
find: /opt/storage/caches/modules-2/files-2.1/redis.clients: No such file or directory
find: /opt/storage/caches/modules-2/files-2.1/org.infinispan: No such file or directory
... 
$ du -hs /opt/storage/
4.0K    /opt/storage/

Any ideas to what is causing find combined with xargs to find files that does not exists? Maybe some race condition where files are somehow deleted before they are found/printed to log?

Possibly related: https://www.linuxquestions.org/questions/linux-newbie-8/find-exec-with-rm-gives-unnecessary-error-747473/#post3646393

but mentions that the solution is to use xargs which is what I am doing.

Update: Based on below comments seems the issue is that deleting a file updates the modified time for the parent folder. Also files and folder will potentially be created during the deletion under the same parent/starting folder.

There is an example in this post: https://stackoverflow.com/a/13869000/363603

on using ctime instead. But from:

https://www.webservertalk.com/linux-touch-command

Changed time The last time the file’s metadata, attribute or content was changed.

so that would give the same issue.

If its possible to combine find with --time=birth:

https://unix.stackexchange.com/a/567590/11740

that would probably be the most robust solution but so far I have not found examples for this.

So there is no "standard" way in linux to do file retention (based on a date threshold) recursively from a starting folder while some parts of the subtree might be updated during the deletion/retention?

Current solution: Based on findings so far I have split into finding all the files for deleting followed by executing the deletion:

# Store path to all files that should be deleted (potentially a lot!)
FILES_TO_DELETE=$(find /some-folder/* -mmin +59)

# Delete the file
rm -rf $FILES_TO_DELETE
5
  • 1
    The issue is that you are deleting directories with rm -rf that find hasn't visited yet. Are you sure you want to delete directories based on the last modified timestamp of the directory? That timestamp is updated when a directory entry is modified (a file or directory added or removed), but it is unaffected by things being added or deleted in subdirectories.
    – Kusalananda
    May 2, 2022 at 19:37
  • I want to delete all files and folder old than N minutes. The result of find is passed to xargs/rm -rf. I don't see how that can result in No such file or directory.
    – u123
    May 2, 2022 at 19:43
  • 1
    @Kusalananda is correct - you're deleting things before you get to them because the recursive flag (and find's output is quasi-random). Just add -type f to limit it to files, and if you want them deleted then the flag is -delete without spawning more processes. May 2, 2022 at 19:57
  • 1
    Let me put it this way: If nothing was deleted or added to the /opt/storage/dir directory for N minutes, but something was added to /opt/storage/dir/subdir just now, should /opt/storage/dir be deleted totally? Because that's what you're doing.
    – Kusalananda
    May 2, 2022 at 19:58
  • 1
    Hm ok so since content might be added while I delete the only way to do this is to make sure I only delete files - e.g. using the -type f option? Then followed by a delete all empty dirs?
    – u123
    May 2, 2022 at 20:06

1 Answer 1

1

You are deleting directories including its contents, and then delete these contents which don't exist anymore, hence the error messages.


It's probably not a good idea to delete directories based on modified time, so you might rather want to do a 2-step approach:

  1. delete files
  2. delete empty directories

-->

find /some-folder/* -type f -mmin +59 -delete \
&& find /some-folder/* -type d -empty -delete

If you really want to remove both files and directories, you could use -prune to not decend into directories that you already deleted:

find /some-folder/* -mmin +59 -exec rm -rf {} \; -type d -prune

Note, that I use -delete (only for files) or -exec rm -rf {} \; instead of xargs .... If you want to use xargs, you should opt for null-delimited output using -print0 and xargs -0. Some of these options might not be available in your find version.

2
  • Splitting like that - your first example - still gives the No such file or directory for most of the files
    – u123
    May 3, 2022 at 9:31
  • If for the first part I instead do: find /some-folder/* -type f -mmin +59 -exec rm -rf {} \; it works (meaning not Not found errors). So maybe the find -delete option is "unpredictable"?
    – u123
    May 3, 2022 at 10:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .