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:


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.


2 Answers 2


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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.