# find: delete folder and sub folders but add exception to two files

I am trying to use the find command to do the following:
Delete a whole folder with files, folders and subfolders except for 2 files, here is an example of what I need:

 test/folder1/file1.txt
test/folder1/file2.txt
test/folder1/subfolder1/
test/folder1/subfolder1/file3.txt
test/folder1/subfolder1/subfolder2/file4.txt
test/folder2/file5.txt
test/folder3/file6.txt


I need to delete everything except for file2.txt and file3.txt

Here is what I already did

 find /test* ! -path '/test/folder1/file2.txt' -a ! -path 'test/folder1/subfolder1/file3.txt'


This will list me all the files except the ones I specified. However if I add -exec rm -rf {} by the end of the command it will delete everything.

I have also tried this other command and didn't work

rm -r  test/folder1/ !(file2.txt|file3.txt)


I don't know much about regular expression so I am trying to make it work by testing commands I found online, however none of them seems to be working.

Don't call rm -rf. As soon as you run it on a directory, that deletes all the files in the directory and the subdirectories, even the ones you wanted to keep. More generally, don't call rm -rf unless you know why a simple rm won't do. Here, rm -f is warranted if you want to be sure that your script won't ask for confirmation to delete a read-only file, but -r is clearly not warranted.

To just delete the files:

find /test* ! -path '/test/folder1/file2.txt' -a ! -path 'test/folder1/subfolder1/file3.txt' -a -exec rm -f {} +


If you also want to delete the directories that become empty, call rmdir on them. Use -depth so that the directory contents are considered before the directory itself.

find /test* ! -path '/test/folder1/file2.txt' -a ! -path 'test/folder1/subfolder1/file3.txt' -a $$-type d rmdir {} \; -o -exec rm -f {} \;$$


You'll get errors from rmdir running on non-empty directories, they're annoying but harmless.

If your find has -delete and -empty (e.g. GNU find), you don't need to call rm and rmdir.

find /test* ! -path '/test/folder1/file2.txt' -a ! -path 'test/folder1/subfolder1/file3.txt' -a ! -type d ! -empty -delete


Look, I also don't know offhand how to do it with find options but you can also use shell scripting in you find:

First delete files:

 find . -type f -exec bash -c \
' [[ "{}" == "./test/folder1/file2.txt" || \
"{}" == "./test/folder1/subfolder1/file3.txt" ]] \
|| rm "{}" ' \;


And then delete all not empty folders:

find .  -type d -exec rmdir {} \; 2>/dev/null