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
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)
- 
        2Can also add-maxdepth 1to the find to stop recursion.Flup– Flup2013-04-04 12:56:23 +00:00Commented Apr 4, 2013 at 12:56
- 
        even this works. clean and simple!!Pranit Bauva– Pranit Bauva2013-04-04 13:05:14 +00:00Commented Apr 4, 2013 at 13:05
- 
        2-deleteis not portable if that matters, you can use-exec rminstead.Chris Down– Chris Down2013-04-08 02:12:20 +00:00Commented Apr 8, 2013 at 2:12
- 
        Ifrm !(*.c)generatesevent not foundin bash, it needs to be proceeded withshopt -s extglob.kenorb– kenorb2015-03-14 18:48:47 +00:00Commented Mar 14, 2015 at 18:48
- 
        As usual, recommendation to first run without-deleteto make sure you didn't make any potentially disastroud mistake.Shadur-don't-feed-the-AI– Shadur-don't-feed-the-AI2016-06-01 07:41:35 +00:00Commented 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
