LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (http://www.linuxquestions.org/questions/linux-general-1/)
-   -   find with -prune and -delete (http://www.linuxquestions.org/questions/linux-general-1/find-with-prune-and-delete-902604/)

sseeg 09-12-2011 10:49 AM

find with -prune and -delete
 
Howdy!

I am trying to go through my filesystem, looking for files that end in ~ (back up files from Emacs) and delete them. The tricky bit is that I have some NFS-mounted directories in /import that sometimes go stale, so I don't want to even go into that directory at all.

I have the following, which prints out everything nicely:

Code:

find / -path /import -prune -o -regex ".*~" -type f -ctime +5 -ls
What I really want to do is repalce the -ls with -delete. But that implies the -depth option which undoes my -prune option. Help!

I thought about using something like:
Code:

find / -path /import -prune -o -regex ".*~" -type f -ctime +5 -exec rm -rf {} \;
but couldn't figure out how to protect the {} enough from odd filenames. Any ideas?

Thanks!!
Seth

thesnow 09-12-2011 10:59 AM

I would use your find command to generate a list of target files (saved to a file), review the list and make any edits, then do a for loop on the list for the deletes.

sseeg 09-12-2011 11:05 AM

Quote:

Originally Posted by thesnow (Post 4469785)
I would use your find command to generate a list of target files (saved to a file), review the list and make any edits, then do a for loop on the list for the deletes.

Thanks, thesnow, but I need it to be automated (this, and similar commands need to run on 20+ servers.

David the H. 09-12-2011 12:29 PM

I don't see why your second one wouldn't work. The names are all handled internally and are never subjected to shell parsing, so odd filenames shouldn't be a problem.

The other usual option is to pipe the names into xargs, using null separators to avoid shell word-splitting.

Code:

find / -path /import -prune -o -regex ".*~" -type f -ctime +5 -print0 | xargs -0 rm -f
Also the -r option to rm shouldn't be necessary, since it's only removing files.


On another note,I wonder if bracketing the the two expressions separately would keep them from affecting each other.
Code:

find / \( -path /import -prune \) -o \( -regex ".*~" -type f -ctime +5 -delete \)
I'm not going to test it myself though. ;)

GazL 09-12-2011 05:13 PM

An alternative approach would be to use the '-xdev' option to stop find crossing mountpoints, but you'll need to explicitly list the filesystems you do want it to process (which is possibly not a bad thing to do anyway)

e.g. for /, /home, and /var (assuming you have a separate /home and /var filesystem - which I always do)
Code:

find / /home /var -xdev -regex ".*~" -type f -ctime +5
You should be able to add '-delete' to that once you're happy with it.

This approach will also prevent it needlessly traversing /proc and /sys and other filesystems that you're not interested in without having to prune them out

sseeg 09-13-2011 08:20 AM

Quote:

Originally Posted by David the H. (Post 4469879)
The other usual option is to pipe the names into xargs, using null separators to avoid shell word-splitting.

Code:

find / -path /import -prune -o -regex ".*~" -type f -ctime +5 -print0 | xargs -0 rm -f

Thank you! That is the solution that works, since xargs will protect the filenames.

sseeg 09-13-2011 08:24 AM

Quote:

Originally Posted by GazL (Post 4470066)
An alternative approach would be to use the '-xdev' option to stop find crossing mountpoints, but you'll need to explicitly list the filesystems you do want it to process (which is possibly not a bad thing to do anyway)

e.g. for /, /home, and /var (assuming you have a separate /home and /var filesystem - which I always do)
Code:

find / /home /var -xdev -regex ".*~" -type f -ctime +5
You should be able to add '-delete' to that once you're happy with it.

This approach will also prevent it needlessly traversing /proc and /sys and other filesystems that you're not interested in without having to prune them out

GazL - The -xdev is a good idea, but it doesn't work by itself. When an NFS mount goes stale (using hard mounting), any "ls" of the parent directory (or any command referencing the NFS link) will hang until the server comes back. That's why we can't go into the /imports directory at all.

GazL 09-13-2011 03:40 PM

Ahh, ok, I'd assumed that -xdev would stop it from running stat() on the mountpoints, I guess it just stops it descending into them. Thanks for the feedback, I'll have to remember that one. :)


If you're using the xargs solution, you'll want to add the '-r' switch for when there aren't any matches.

phrenq 01-10-2013 04:06 AM

Quote:

Originally Posted by David the H. (Post 4469879)
On another note,I wonder if bracketing the the two expressions separately would keep them from affecting each other.
Code:

find / \( -path /import -prune \) -o \( -regex ".*~" -type f -ctime +5 -delete \)
I'm not going to test it myself though. ;)

Just to precise, I tested it, and this is find's answer to equivalent command of
Code:

find / \( -path /import -prune \) -o \( -depth -regex ".*~" -type f -ctime +5 \):
Quote:

find: warning: you have specified the -depth option after a non-option argument (, but options are not positional (-depth affects tests specified before it as well as those specified after it). Please specify options before other arguments.
So it unfortunately doesn't do the job. Using xargs seems to be the best option.


All times are GMT -5. The time now is 09:22 PM.