3 Ways to Delete All Files in a Directory Except One or Few Files with Extensions

In Linux, a shell pattern is a string that consists of the following special characters, which are referred to as wildcards or metacharacters:

* – matches zero or more characters

? – matches any single character

[seq] – matches any character in seq

[!seq] – matches any character not in seq


There are three possible methods we shall explore here, and these include:


Delete Files Using Extended Pattern Matching Operators


The different extended pattern matching operators are listed below, where pattern-list is a list containing one or more filenames, separated using the | character:

*(pattern-list) – matches zero or more occurrences of the specified patterns

?(pattern-list) – matches zero or one occurrence of the specified patterns

+(pattern-list) – matches one or more occurrences of the specified patterns

@(pattern-list) – matches one of the specified patterns

!(pattern-list) – matches anything except one of the given patterns


To use them, enable the extglob shell option as follows:

# shopt -s extglob


1. To delete all files in a directory except filename, type the command below:

$ rm -v !("filename")


2. To delete all files with the exception of filename1 and filename2:

$ rm -v !("filename1"|"filename2") 


3. The example below shows how to remove all files other than all .zip files interactively:

$ rm -i !(*.zip)


4. Next, you can delete all files in a directory apart from all .zip and .odt files as follows, while displaying what is being done:

$ rm -v !(*.zip|*.odt)


Once you have all the required commands, turn off the extglob shell option like so:

$ shopt -u extglob


Delete Files Using Linux find Command


Under this method, we can use find command exclusively with appropriate options or in conjunction with xargs command by employing a pipeline as in the forms below:

$ find /directory/ -type f -not -name 'PATTERN' -delete
$ find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I {} rm {}
$ find /directory/ -type f -not -name 'PATTERN' -print0 | xargs -0 -I {} rm [options] {}


5. The following command will delete all files apart from .gz files in the current directory:

$ find . -type f -not -name '*.gz'-delete


6. Using a pipeline and xargs, you can modify the case above as follows:

$ find . -type f -not -name '*gz' -print0 | xargs -0  -I {} rm -v {}


7. Let us look at one additional example, the command below will wipe out all files excluding .gz, .odt, and  .jpg files in the current directory:

$ find . -type f -not \(-name '*gz' -or -name '*odt' -or -name '*.jpg' \) -delete


Delete Files Using Bash GLOBIGNORE Variable


This last approach however, only works with bash. Here, the GLOBIGNORE variable stores a colon-separated pattern-list (filenames) to be ignored by pathname expansion.


To employ this method, move into the directory that you wish to clean up, then set the GLOBIGNORE variable as follows:

$ cd test
$ GLOBIGNORE=*.odt:*.iso:*.txt


In this instance, all files other than .odt, .iso, and .txt files with be removed from the current directory.


Now run the command to clean up the directory:

$ rm -v *


Afterwards, turn off GLOBIGNORE variable:



Note: To understand the meaning of the flags employed in the commands above, refer to the man pages of each command we have used in the various illustrations.


Was this answer helpful? 0 Users Found This Useful (0 Votes)