When I am using wildcards with ls
command, it works.
$ ls '*.{mp3,ogg}' # Showing only two formats in the command
cannot access *.mp3: No such file or directory
1.ogg 2.ogg 3.ogg
but using find command doesn't work
$ find ~ -iname '*.{mp3,ogg}'
What is the error in the line?
I think this should work for you
find ~ -name "*.mp3" -o -name "*.ogg"
-o is equivalent to boolean or
If you enable extglob (shopt -s extglob
), you can use *.@(ogg|mp3)
.
shopt -s extglob
printf '%s\n' *.@(mp3|ogg)
If you need recursion too, enable globstar (requires bash 4.0 or newer)
shopt -s extglob globstar
printf '%s\n' **/*.@(mp3|ogg)
When you use ls *.{mp3,ogg}
, you are combining brace expansion and pathname expansion. What happens is:
ls *.{mp3,ogg}
ls *.mp3 *.ogg # after brace expansion
ls '*.mp3' 1.ogg 2.ogg 3.ogg # after pathname expansion
If there's no matching files for a glob, the glob will just be passed on unchanged. And ls
will treat it as a literal filename; it doesn't know about globs/wildcards.
The find ~ -iname '*.{mp3,ogg}'
doesn't work because find
doesn't do brace expansion, that's a bash feature.
This one provides you with even those files which do not have mp3 or audio extension.
find -print0 | xargs -0 file -F '//' | awk -F '//' 'tolower($2) ~ /audio/ { print $1 }'
which interprets to:
find . -print0
Find (list) every file and output with a null terminator
xargs -0 file -F '//'
Run file(1)
with the stdin (or piped input), delimited by null character, as the first argument.
file -F '//'
Delimit file name and its type by //
as it neither appears in a UNIX filename nor as a file type.
awk -F '//' '...'
Use the //
delimiter as field separator. The awk script case-insensitively matches the occurrence of audio
in the second field (ie the file type as reported by file(1)
) and for every match, prints the file path.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With