Bash globbing that matches all files except those with a specific extension, that works on filenames that include dot characters
*.!(mp3)
matches on foo.bar.mp3
because that's foo.
followed by bar.mp3
which is not mp3
.
You want !(*.mp3)
here, which matches anything that doesn't end in .mp3
.
If you want to match files whose name contains at least one .
(other than a leading one which would make them a hidden file) but don't end in .mp3
, you could do !(*.mp3|!(*.*))
.
There's also the GLOBIGNORE
variable:
The
GLOBIGNORE
shell variable may be used to restrict the set of file names matching a pattern. IfGLOBIGNORE
is set, each matching file name that also matches one of the patterns inGLOBIGNORE
is removed from the list of matches. If thenocaseglob
option is set, the matching against the patterns inGLOBIGNORE
is performed without regard to case. The filenames.
and..
are always ignored whenGLOBIGNORE
is set and not null. However, settingGLOBIGNORE
to a non-null value has the effect of enabling thedotglob
shell option, so all other filenames beginning with a ‘.
’ will match. To get the old behavior of ignoring filenames beginning with a ‘.
’, make ‘.*
’ one of the patterns inGLOBIGNORE
. Thedotglob
option is disabled whenGLOBIGNORE
is unset.
$ touch a.b.mp3 .c.mp3 foo.tgz .bar
$ echo *
a.b.mp3 foo.tgz
$ shopt -s extglob; echo *.!(mp3)
a.b.mp3 foo.tgz
$ GLOBIGNORE='*.mp3'; echo *
.bar foo.tgz
the simplest way I can think of:
find ${path-to-folder} -type f | grep -vE ".*\.mp3$"
You find all files in a folder and pipe it to a reverse extended grep:
Find all files in a location
find ${path-to-folder} -type f
Reverse grep and use a regex to filter by extension
grep -vE ".*\.mp3$"
Grep flags:
-v
reverse grep-E
extended grep (use of regex)
Regex explained:
.*
means from 0 to whatever char count, any possible char\.
looks for the actual dotmp3
for the string that forms the extension$
stands for EOL