Tuesday, April 30, 2024
 Popular · Latest · Hot · Upcoming
68
rated 0 times [  68] [ 0]  / answers: 1 / hits: 31382  / 3 Years ago, fri, september 24, 2021, 11:00:02

I need to remove all files with .gif extension except one file with name say "filename.gif". What is the optimal way to go about doing this in terminal?



The command rm *.gif removes all gif files including the file filename.gif.


More From » bash

 Answers
1

Here's the simple solution you should probably use:



mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif


There's nothing special about the .keep extension, this just makes it so that the filename temporarily doesn't end in .gif.



If you must not rename the file (and there are scripting situations where this is important):



for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done


Or you can write it shorter like this:



for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done


You may prefer to use find instead; it's very powerful, you might consider it more readable, and it better handles weird filenames with characters like * in them.



find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete


I've used the -not operator for readability, but if POSIX compliance is important--if you're not using GNU find, or if this is for a script you intend to redistribute to others or run on a variety of systems--you should use the ! operator instead:



find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete


One handy thing about find is that you can easily modify the command for case-insensitivity, so that it finds and deletes files with extensions like .GIF too:



find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete


Please note that I've used -iname in place of -name for the search pattern *.gif but I have not used it for filename.gif. Presumably you know exactly what your file is called, and -iname will match alternate capitalization not just in the extension, but anywhere in the filename.



All these solutions only delete files residing immediately in the current directory. They don't delete files not contained in the current directory, and they don't delete files that reside in subdirectories of the current directory.



If you want to delete files everywhere contained within the current directory (that is, including in subdirectories, and in subdirectories of those subdirectories, and so forth--files contained within the current directory or any of its descendants), use find without maxdepth -1:



find . -not -name 'filename.gif' -name '*.gif' -delete


Be careful with this!



You can also set other values with -maxdepth. For example, to delete files in the current directory and its children and grandchildren but not any deeper:



find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete


Just make sure you never put -delete first, before the other expressions! You'll see I've always put -delete at the end. If you put it at the beginning, it would be evaluated first, and all the files under . (including files not ending in .gif and files in deep sub-sub-sub...directories of .) would be deleted!



For more information, see the manual pages for bash and sh and for the commands used in these examples: mv, rm, [, and (especially) find.


[#32677] Sunday, September 26, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
imberst

Total Points: 370
Total Questions: 107
Total Answers: 123

Location: French Polynesia
Member since Tue, Jul 7, 2020
4 Years ago
imberst questions
;