Automatically create extm3u (extended .m3u) playlist in GNU/Linux

I couldn’t find a satisfactory command line method to create extended .m3u playlists in Debian.  The best is a perl script which you can find at  It’s really good and very quick but only supports mp3, ogg and flac files.  I modified it to also support mp4/m4a and submitted a patch but the author wasn’t interested enough to respond.  In any case I want a tool that will support numerous audio formats so I wrote a bash script which uses normal GNU utilities such as awk and bc along with ffprobe (part of ffmpeg) and consequently can write an extended .m3u for any files that (your installed version of)  ffmpeg supports. The script can be found at

20 March 2013: New version at supports opus codec files and has a fix for problem with wrong track duration (introduced by recent changes in ffmpeg/ffprobe)
21 April 2014: New version at same link as above, now works with locales which use , for decimal divider. Thanks to Tina Keil.

22 December 2015: updated version at same link to support relative paths, thanks to Dave.

9 January 2016 removed problematic relative paths function.

I’ll just post the usage/options here so you can see what it does (it isn’t complicated):

bashplaylist [options] {-o out} <directory>

-p  writes the file names in .m3u with full path
(default is simple file name without path)

-r  recurses through subdirectories and writes file names with
full path

-o <output directory>  (default is target directory)

bashplaylist finds the audio files in the directory, parses
the metadata, then writes an extended .m3u playlist

bashplaylist understands the same files as  your
installed version of ffmpeg.

If bashplaylist fails please check output directory exists
and is writeable.

#june 07 2012 edited script to remove unwanted / in regex which prevented ogg files from being parsed


14 Responses to “Automatically create extm3u (extended .m3u) playlist in GNU/Linux”

  1. Nick B. Says:

    Excellent! Just what I was looking for. I used a Debian package named
    ‘libapache2-mod-musicindex’ to create the extended playlists, but the package is held up at the moment and I needed something to automate
    creating EXTM3U. Thank you.

  2. takla Says:

    I’m glad you find it useful. I didn’t know about the apache mod so that looks interesting.

    I made a newer version of bashplaylist that has some additions for Rockboxed audio player devices (it still works the same as the old script in other respects). It writes utf-8 playlists and can also write the m3u8 file with the file paths formatted so that they are absolute paths on the target player. It is specific to my Sansa Clip+ and iRiver H140 and H340 players and mount points but is very easily adapted for any player with a persistent mount point which uses playlist files with absolute path names. This is meaningless for most people but might be very useful for a few.

    Run without options or arguments for usage:

    bashplaylist [options] {-o out}

    -D Don’t overwrite existing playlist (default is to replace)

    -s Simple m3u8 playlist instead of extended m3u8

    -p writes the file names with full path
    default is local file names without full path

    -o (default is input directory) (implies -p)

    -r recurses through subdirectories and writes file names with
    full path

    -c Format playlist for Sansa Clip+ Internal Memory (implies -p)
    -C Format playlist for Sansa Clip+ MicroSDHC (implies -p)
    -H Format playlist for iriver H10/100/300 series players (implies -p)
    You MUST change the MicroSDHC card label and mount point in
    the sed expressions to the ACTUAL MicroSDHC card label and
    mount point on your OS. The Clip internal storage and iRiver H
    values are quite generic but Clip external storage values could be
    anything – user must check this.

    If bashplaylist fails please check output directory exists
    and is writeable.

    It can be found at

  3. Joseph Says:

    Hi there,

    This sounds like a useful script. I’ve tried using your newest version of the script. I haven’t got it to work, perhaps I’m doing something incorrect. I made a directory with mp3 files and run the script, but I keep getting just the default usage function only executes. I have tried adding parameters as well. However, as I understand it, the script can just be executed in the current directory of mp3 files. Nothing seems to work. I’m using Ubuntu and have installed the dependency ffmpeg.


    • takla Says:

      bashplaylist takes a directory as argument. So if you have a directory home/user/music/ which contains 01.mp3 02.mp3 03.mp3 etc etc then you would do:

      bashplaylist home/user/music/


      bashplaylist home/user/music/*.mp3

      You can see this is specified in the usage:

      bashplaylist [options] {-o out} directory

      The argument must be a directory or directories, not a file or files.

  4. Tina Keil Says:

    Thanks for this script. Works great. I’m on Arch with German language setting and was getting “printf invalid number” errors, so the script was not adding the length of the titles in seconds. I had to add


    Also had to install “bc”, since this was not standard on my system.

    Thanks for sharing!

    • takla Says:

      Hi Tina. Thank you for your kind comments. As a monolingual English speaking Englishman residing in England and using a UK keyboard and GB Locale I hadn’t considered locales where , is used instead of . for the decimal divider. Stimmt das? Natürlich! Thanks for pointing that out. I will update the script accordingly.

      Amongst binary distributions bc being absent seems to be a peculiarity of Arch, due to its l33t quest to purge its base install of useful documentation, legally required copyright licenses and apparently even basic GNU utilities. I believe this is all characterised as “cruft” or “bloat”. What to do?

      btw if you use #!/bin/sh instead of #!/bin/bash the script cannot be guaranteed to work as it is a bash script (it contains bashisms). In Arch I think you’ll find that /bin/sh is symlinked to /bin/bash so fortunately #!/bin/sh works for you(™) but in other UNIX-like operating systems this isn’t always the case. For example, Debian and derivatives have dash as the default shell, and most BSDs will use something else such as ksh, so that is why #!/bin/bash is explicitly defined in the script.

      Thanks again

      • Tina Keil Says:

        Hi Takla, dein Deutsch ist prima 😉 Thanks for pointing out the bash / sh issue. Sorry, I didnt actually change it. It was a paste and copy error on my side, from the page where I found the locale fix. Sorry, didn’t mean to add to any confusion. So #!/bin/bash it is and thanks for explaining the the problems it can cause if used 🙂

        Will be back in good old UK (Exeter) on Friday 🙂

        best tina

      • takla Says:

        Over thirty years ago I spent many long, long, so long hours at school learning German. I can still remember everything I learned: Karl ist ein hund. Spitz ist meine Schwester. Ingrid ist mein Bruder. Brötchen mit Butter und Marmelade bitte. Rauchen verboten! Aber Professor, das ist doch auch illegal und unmoralisch? Warum ich? I knew it would all pay off in the end!

        btw as a visitor to Devon how did you react when encountering people who routinely address you as “lover”, “my lover” or “my handsome” even when you are only buying a bus ticket or a newspaper? I liked it and felt both flattered and strangely excited but I’m easy.

      • Tina Keil Says:

        Well you certainly had a very good teacher, judging from your perfect gramatic and no spelling errors what so ever. Am impressed! 🙂 Love the questions from the professor. Must remember that one – might come in handy.

        Yes, I did get warned about the Devon way 😉 and have been called “my lover” on occassion … I think it’s quite sweet somehow … makes you feel less of a stranger and so on. Will be spending the next 2-3 years there at the Uni, which has a lovely campus, amongst other things.

        Will keep an eye on your blog, am no linux expert and always appreciate places where I can learn.

  5. Jochen Says:

    just stumbled across your script today and tried it out. I found it to be working quite nicely on my Raspberry Pi.

    However, the title tags were not determined correctly for some of my mp3 files. It turned out that this was the case for all files that have several tags (or streams as its called in ffprobe). In my case I had files that had an embedded cover image. These images apparently get their own video stream tag which unfortunately also has an empty title attribute.

    My fix was to modify the ffprobe command so that it filters its output to audio streams only. This eliminates duplicate title tag in my case. The modified command appends just “-select_streams a” to the options like this;

    ffprobe -v quiet -show_format -show_streams -select_streams a “$f”>”$DATA”

    Hope this helps someone


  6. Dave Says:

    Here’s an enhancement of the rockbox-enabled version. This one adds support for relative paths.

  7. Steen Says:

    Thanks for this, my flac files come with no titles in the files, and then also in the music player.
    And the -R option does not handle my file names with spaces, or am I doing something wrong?

    • takla Says:

      I can’t find a problem with empty titles…unless the files actually don’t have a name tag. Check your files.

      You’re right about the -R “relative path” option being faulty. It was contributed recently and I should have checked it more carefully. For the moment I’m removing Dave’s relative path function. I may add my own later.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: