I have a directory which contains all the C programs. I have also compiled them at the creation time so as to check my code. There are a lot of programs nearly 100 of them. So I want a BASH script that would check whether the file ends with ".c". If it does then it does not do anything, which if it doesn't then it would remove them. Suppose one of my file name is "Hello.c" then I have named its binary during compile time as "Hello". So can anyone make this script for me?

3 Answers 3


You can use the -delete flag of find (first test with -ls)

find -not -name "*.c" -delete

If you do not want to use find, but only files in the current directory, you could do

rm !(*.c)

Make sure in bash that with shopt -s extglob the correct globbing is set. Additionally, if you have globstar set (shopt -s globstar), you can act recursively (for bash versions above 4):

rm **/!(*.c)
  • 2
    Can also add -maxdepth 1 to the find to stop recursion.
    – Flup
    Commented Apr 4, 2013 at 12:56
  • even this works. clean and simple!! Commented Apr 4, 2013 at 13:05
  • 2
    -delete is not portable if that matters, you can use -exec rm instead.
    – Chris Down
    Commented Apr 8, 2013 at 2:12
  • If rm !(*.c) generates event not found in bash, it needs to be proceeded with shopt -s extglob.
    – kenorb
    Commented Mar 14, 2015 at 18:48
  • As usual, recommendation to first run without -delete to make sure you didn't make any potentially disastroud mistake. Commented Jun 1, 2016 at 7:41

I always prefere find in such cases. You have not worry about special filenames and you may handle different filetypes. If you like to delete files only, you should add -type f to your options. So my favorite solution is:

find -not -name "*.c" -type f -delete

But be careful. Testing such commands is always a good idea.


Activate ksh extended wildcard patterns with the command shopt -s extglob (you can put this in your ~/.bashrc). Then the pattern !(*.c) matches all files in the current directory except the ones that match *.c:

rm !(*.c)

This is pretty dangerous as it deletes .txt files, .h files, etc. A less drastic command would be

rm !(*.*) *.o

This still deletes README, Makefile, etc. You should maybe only delete executable files:

find . -type d -prune -o -type f -perm -100 -exec rm {} +

Shorter, if your find supports it:

find . -maxdepth 1 -type f -perm -100 -delete

You must log in to answer this question.

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