5

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?

21

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 Apr 4 '13 at 12:56
  • even this works. clean and simple!! – Pranit Bauva Apr 4 '13 at 13:05
  • 2
    -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 '16 at 7:41
5

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.

4

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

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.