Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am trying to get all my MP3 to have the BPM registered. I did find software for that via this Super User question.

I installed bpmdj, vorbis-tools flac python-mutagen and copied the bash script from the named Super User question (see below). Now, the problem is that this script gives me two errors:

  1. /home/jeroen/ line 67: warning: here-document at line 4 delimited by end-of-file (wantedHELP')`
  2. /home/jeroen/ line 68: syntax error: unexpected end of file

These are the last two lines of the script. I assume the script did work for the OP, but now no longer works on Ubuntu 12.04.

I am new to bash scripting, and I tried to find the errors, but to no avail. Any help would be appreciated.


function display_help() {
    cat <<-HELP
            Recursive BPM-writer for multicore CPUs.
            It analyzes BPMs of every media file and writes a correct tag there.
            Usage: $(basename "$0") path [...]
    exit 0

[ $# -lt 1 ] && display_help

#=== Requirements
requires="bpmcount mid3v2 vorbiscomment metaflac"
which $requires > /dev/null || { echo "E: These binaries are required: $requires" >&2 ; exit 1; }

#=== Functions

function bpm_read(){
    local file="$1"
    local ext="${file##*.}"
    declare -l ext
    # Detect
    { case "$ext" in
        'mp3')  mid3v2 -l "$file" ;;
        'ogg')  vorbiscomment -l "$file" ;;
        'flac') metaflac --export-tags-to=- "$file" ;;
        esac ; } | fgrep 'BPM=' | cut -d'=' -f2
function bpm_write(){
    local file="$1"
    local bpm="${2%%.*}"
    local ext="${file##*.}"
    declare -l ext
    echo "BPM=$bpm @$file"
    # Write
    case "$ext" in
        'mp3')  mid3v2 --TBPM "$bpm" "$file" ;;
        'ogg')  vorbiscomment -a -t "BPM=$bpm" "$file" ;;
        'flac') metaflac --set-tag="BPM=$bpm" "$file"
                mid3v2 --TBPM "$bpm" "$file" # Need to store to ID3 as well :(

#=== Process
function oneThread(){
    local file="$1"
    #=== Check whether there's an existing BPM
        local bpm=$(bpm_read "$file")
        [ "$bpm" != '' ] && return 0 # there's a nonempty BPM tag
    #=== Detect a new BPM
    # Detect a new bpm
    local bpm=$(bpmcount "$file" | grep '^[0-9]' | cut -f1)
    [ "$bpm" == '' ] && { echo "W: Invalid BPM '$bpm' detected @ $file" >&2 ; return 0 ; } # problems
    # Write it
    bpm_write "$file" "${bpm%%.*}" >/dev/null

NUMCPU="$(grep ^processor /proc/cpuinfo | wc -l)"
find $@ -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac)' \
    | while read file ; do
        [ `jobs -p | wc -l` -ge $NUMCPU ] && wait
        echo "$file"
        oneThread "$file" &
share|improve this question
up vote 2 down vote accepted

The script contains a heredoc, which is <<-HELP. It allows you to include literal strings between two identifiers. This identifier is specified after the <<, and it's HELP.

In the script you have, there's a special syntax element with a - between << and the identifier. It allows the identifier to be recognized even if it's indented by tabs, so you could write:

cat <<-HELP
   some indented text

Here, ___ would be a tab. Now, in your case, it's probably indented by multiple spaces, which is why the end of the heredoc isn't found.

There are two solutions for this:

  • Change your indentation from spaces to tabs.
  • Move the HELP identifier to the start of the line.

If you use an editor with proper syntax highlighting (or one that shows spaces vs. tabs), you should see this error:

share|improve this answer
Thanks! That worked. I changed the spaces to a tab. I doubt I would have found that on my own. – Desd Dec 24 '12 at 14:50
No problem! Updated my answer with a screenshot from an editor — if it has proper syntax highlighting you'll be able to spot these things! – slhck Dec 24 '12 at 15:15

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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