Search mp3 collection for songs with a certain song length

First install mp3info, it should be in the repositories of your distribution (you have not said, so I assume you are using Linux of some sort). If you have a debian-based distribution, you can do so with

sudo apt-get install mp3info

Once mp3info is installed, you can search the directory music for songs of a certain length with this command:

find music/ -name "*mp3" | 
  while IFS= read -r f; do 
   length=$(mp3info -p "%S" "$f"); 
   if [[ "$length" -ge "180" && "$length" -le "195" ]]; then 
     echo "$f"; 
   fi;  
done

The command above will search music/ for mp3 files, and print their name and length if that length is grater or equal to 180 seconds (3:00) and less than or equal to 195 seconds (3:15). See man mp3info for more details on its output format.

If you want to be able to enter times in MM:SS format, it gets a bit more complex:

#!/usr/bin/env bash

## Convert MM:SS to seconds.
## The date is random, you can use your birthday if you want.
## The important part is not specifying a time so that 00:00:00
## is returned.
d=$(date -d "1/1/2013" +%s);

## Now add the number of minutes and seconds
## you give as the first argument
min=$(date -d "1/1/2013 00:$1" +%s);
## The same for the second arument
max=$(date -d "1/1/2013 00:$2" +%s);

## Search the target directory for files
## of the correct length.
find "$3" -name "*mp3" | 
  while IFS= read -r file; do 
   length=$(mp3info -p "%m:%s" "$file"); 
   ## Convert the actual length of the song (mm:ss format)
   ## to seconds so it can be compared.
   lengthsec=$(date -d "1/1/2013 00:$length" +%s);

   ## Compare the length to the $min and $max
   if [[ ($lengthsec -ge $min ) && ($lengthsec -le $max ) ]]; then 
       echo "$file"; 
   fi; 
done

Save the script above as findmp3 and run it like this:

findmp3 3:00 3:15 music/

I doubt that there's an existing findmp3 tool. Following the unix philosophy, it can be built from find to find .mp3 files, another tool to report the length of each file that find finds, and some shell/text processing glue.

SoX is a commonly available utility to work with sound files (sox is to sound what sed or awk are to text files). The command soxi displays information about a sound file. In particular, soxi -D prints the duration in seconds.

For each .mp3 file, the snippet below calls soxi and parses its output. If the duration is within the desired range, the sh call returns a success status, so the -print action is executed to print the file name.

find /music/mp3/ebm -type f -name .mp3 -exec sh -c '
    d=$(soxi -D "$0")
    d=${d%.*} # truncate to an integer number of seconds
    [ $((d >= 3*60 && d < 3*60+15)) -eq 1 ]
' {} \; -print

In bash, ksh93 or zsh, you can use recursive globbing instead of find. In ksh, run set -o globstar first. In bash, run shopt -s globstar first. Note that in bash (but not in ksh or zsh), **/ recurses through symbolic links to directories.

for f in /music/mp3/ebm/**/*.mp3; do
  d=$(soxi -D "$0")
  d=${d%.*} # truncate to an integer number of seconds (needed in bash only, ksh93 and zsh understand floating point numbers)
  if ((d >= 3*60 && d < 3*60+15)); then
    echo "$f"
  fi
done

Tags:

Mp3

Find