Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 21 down vote accepted

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

share|improve this answer

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
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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