7

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?

3
  • 1
    Brace expansion and pathname expansion is not done for quoted words, so you must've run ls *.{mp3,ogg} to get that output, not ls '*.{mp3,ogg}'
    – geirha
    Commented Aug 13, 2012 at 5:29
  • 1
    what about m4a files etc? you should rely on file instead.
    – phil294
    Commented Nov 27, 2017 at 15:20
  • Using the "file" utility and grep on "audio" unfortunately is NOT relable, as the file output is not well defined. E.g. on an AAC audio file it reports: MPEG ADTS, AAC, v4 LC, 44.1 kHz, stereo Also you may find avi video files with audio (most likeliy with videos ...) E.g. on an avi file it reports: RIFF (little-endian) data, AVI, 672 x 368, 25.00 fps, video: XviD, audio: MPEG-1 Layer 3 (stereo, 48000 Hz) Thus using "file" gives false positives and also false negatives.
    – Chris56
    Commented Aug 29, 2021 at 5:06

7 Answers 7

17

I think this should work for you

   find ~ -name "*.mp3" -o -name "*.ogg"

-o is equivalent to boolean or

0
4

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.

4

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.

2
  • This will also match files with 'audio' in their path, whether they are truly audio files or not.
    – Ben Amos
    Commented Jan 18, 2021 at 0:25
  • @BenAmos Yes, you're right. I've updated the answer to fix that issue.
    – Hritik
    Commented Jan 19, 2021 at 20:16
2

Here is one I just did . . .

for .ogg and .mp3

         find Music | grep '/*.ogg\|/*.mp3' | sort -u
1

find does not support the full shell wildcard syntax (specifically, not the curly braces). You'll need to use something like this:

find ~ -iname '*.mp3' -o -iname '*.ogg'
0

what about?

file * | grep audio
2
  • This one wouldn't check in subdirectories.
    – Hritik
    Commented Jan 15, 2020 at 14:51
  • find . -exec file {} \; | grep audio -i, however, this doesn't work for all audio files
    – sezanzeb
    Commented May 14, 2023 at 19:13
0
find . -exec file {} --mime-type \; | grep "audio\|video"

might do the trick. The mime type of my m4a files is video/mp4, so I need to grep for that as well.

1
  • is the video bit needed? Searching for video files is tricky due to mp4, as we'd have to grep for something like video/|audio/mp4. But for sound files, grepping for audio should suffice.
    – laur
    Commented Jan 8 at 1:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.