How do I delete files of certain extension that don't have a given string in their filename?
I have a directory with files of many extensions in it. I would like to recursively delete *.srt
files (and *.srt
files only) which don't end with -en.srt
(where srt
is an extension). I've come up with the following solution and it seems to work fine, however, I'd like to know whether it is 100% correct.
find . -name "*.srt" ! -name "*-en.srt" -type f -exec rm -rf {} \;
! -- First read the answer completely then use it if you like it -- !
Your command is correct, however there is no need to use -rf
as rm
parameters. because you are removing files and not directories.
Another clear way to write it is (it's almost same as your command):
find -name '*.srt' -and -not -name '*-en.srt' -type f -exec rm '{}' \;
or as @steeldriver suggested you can use:
find -name '*.srt' -and -not -name '*-en.srt' -type f -ok rm '{}' \;
It will ask for your permission to remove each founded file.
You can also use -delete
instead of rm {} \;
however be aware of its dangers:
Don't forget that the find command line is evaluated as an expres‐ sion, so putting -delete first will make find try to delete everything below the starting points you specified. When testing a find command line that you later intend to use with -delete, you should explicitly specify -depth in order to avoid later surprises. Because -delete implies -depth, you cannot usefully use -prune and -delete together.
It is always a good idea to test what is going to happen before doing the actual job, so I suggest running:
find -name '*.srt' -and -not -name '*-en.srt' -type f | grep -i en.srt
If it return nothing then the actual command will work without any problem and you are good to go... or even:
find -name '*.srt' -and -not -name '*-en.srt' -type f | less
to check what's going to be removed.
And do not forget to quote '{}'
:
(when find is being invoked from a shell) it should be quoted (for example, '{}') to protect it from interpretation by shells.
Let’s do it solely with bash
globbing: With the extglob
and globstar
options enabled,
rm **/!(*-en).srt
deletes every file ending in .srt
excluding anything ending in -en.srt
from the current as well as any subdirectory.
If you‘re not sure about an expansion like this, test by prepending echo
(see example below).
Example
$ tree
.
├── 01.srt
├── 02.srt
├── no-en.srt
├── not-en.srt
├── subdir
│ ├── 01.srt
│ ├── 02.srt
│ ├── no-en.srt
│ └── not-en.srt
└── unrelated.png
$ shopt -s extglob globstar
$ echo rm **/!(*-en).srt
rm 01.srt 02.srt subdir/01.srt subdir/02.srt
$ rm **/!(*-en).srt
$ tree
.
├── no-en.srt
├── not-en.srt
├── subdir
│ ├── no-en.srt
│ └── not-en.srt
└── unrelated.png
Explanations
-
**/
– with theglobstar
option enabled this matches any number of directories and subdirectories -
!(*-en)
– with theextglob
option enabled this matches anything except the given pattern, so anything not ending in-en