2

I am trying to find a way to delete all files and directories older than 30 days in a specific path. But in that path there is one specific directory that I don't want to be deleted or modified. I have been reading up on -prune but can't seem to get it to work. The command I have tried so far is:find "<path to directory" -prune -o -name "<name of excluded directory" -type f -mtime +30 -exec rm {} +

2 Answers 2

6

You appear to have the logic of your find command mixed up. If you want to exclude a directory named excludeme and otherwise print filenames, you would write:

find /path/to/top/directory -name excludeme -prune -o -type f -print

Recall that -o is a logical OR, so any conditions that effect -prune need to be on the same side of the -o as the -prune command.

With that in mind, we end up with:

find "<path to directory" \
  -name "<name of excluded directory> -prune -o \
  -type f -mtime +30 -exec rm {} +
1

One step method

If you want to delete all files and directories (not only files), you should protect the directory itself, not only the files and d in its directory tree. (The problem is easier if you only delete files.) This can be done with something like the following:

Let us assume the following file structure (borrowed from another test example),

$ find
.
./tarfile
./work
./work/file1
./work/dir 4
./work/dir 4/file 1
./work/file2
./work/dir5
./work/dir5/sub1
./work/dir5/sub2
./work/ttt
./work/dir1
./work/dir1/file1
./work/dir1/file2
./work/dir1/file 3
./work/dir2
./work/dir2/file1
./work/dir2/file2
./work/dir3
./work/dir3/file1
./work/dir3/file2
./work/dir3/file3
./work/rsync-by-folder
./backup
./backup/dir 4
./backup/dir 4/file 1
./backup/dir1
./backup/dir1/file1
./backup/dir1/file2
./backup/dir1/file 3
./backup/dir2
./backup/dir2/file1
./backup/dir2/file2
./backup/dir3
./backup/dir3/file1
./backup/dir3/file2
./backup/dir3/file3

The following command line excludes the directory ./work/dir2 (and path to it) and removes everything else (files and directories),

$ find . -mindepth 1 -maxdepth 2 -mtime +45 -not \( -path ./work -or -path './work/dir2' \) -exec echo rm -r {} +

or (in order to get one line per rm instance)

$ find . -mindepth 1 -maxdepth 2 -mtime +45 -not \( -path ./work -or -path './work/dir2' \) -exec echo rm -r {} \;
rm -r ./work/file1
rm -r ./work/dir 4
rm -r ./work/file2
rm -r ./work/dir5
rm -r ./work/ttt
rm -r ./work/dir1
rm -r ./work/dir3
rm -r ./work/rsync-by-folder
rm -r ./backup
rm -r ./backup/dir 4
rm -r ./backup/dir1
rm -r ./backup/dir2

Two step method

A maybe safer alternative is to do it in two steps (less risk for mistakes when setting up the find command lines). The first step matches what is already shown in the original question and the first answer, to delete the files except in the directory tree, that should be protected. In my example it matches

$ find . -mtime +45 -not -path '*/dir2/*' -type f -exec rm -r {} +

The following files and directories remain

$ find -printf "%y %p\n"
d .
f ./tarfile               # too new (dangerous location if important to keep)
d ./work
d ./work/dir 4
d ./work/dir5
d ./work/dir5/sub1
d ./work/dir5/sub2
d ./work/dir1
d ./work/dir2
f ./work/dir2/file1
f ./work/dir2/file2
d ./work/dir3
d ./backup
d ./backup/dir 4
d ./backup/dir1
d ./backup/dir2
f ./backup/dir2/file1
f ./backup/dir2/file2
d ./backup/dir3

Now we remove the empty directories. The following method is not sofisticated, and needs repetition until whole trees of empty directories are removed. You are welcome to suggest a more direct method. The rm option -d deletes empty directories.

find -type d -exec rm -d {} +

There will be complaints that some directories are not empty. We have the following result,

$ find -printf "%y %p\n"
d .
f ./tarfile
d ./work
d ./work/dir5             # This is an empty directory
d ./work/dir2
f ./work/dir2/file1
f ./work/dir2/file2
d ./backup
d ./backup/dir2
f ./backup/dir2/file1
f ./backup/dir2/file2

Repeat:

find -type d -exec rm -d {} +

and check the result:

$ find -printf "%y %p\n"
d .
f ./tarfile               # too new (dangerous location if important to keep)
d ./work
d ./work/dir2
f ./work/dir2/file1
f ./work/dir2/file2
d ./backup
d ./backup/dir2
f ./backup/dir2/file1
f ./backup/dir2/file2

Now the directory tree contains only what should be protected.

You must log in to answer this question.

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