Managing music and podcasts with bash scripts

Image source:

For a long time I used iTunes as the main tool for managing my music and podcasts and for syncing them up to my phone and portable media players. I was never a great fan, primarily because it tied me to using Windows on a daily basis, whereas Linux is my preferred desktop OS. Now whilst my main device was an iPhone I had no choice.

iTunes just about did the job I needed but there were aspects of it that grated. Most annoying was that it couldn’t monitor my main music directory and automatically add new media.

I recently switched to an Android phone (a Samsung Galaxy S) and this opened up alternative possibilities. It could be mounted as a plain old USB disk which meant I could manage my phone from my Linux desktop. I tested out many of the available media players and managers – Rhythmbox, Banshee, Amarok, Winamp (with wine), and Songbird – but none of them matched the full range of functionality I required. Specifically:

  • Constantly monitor my media library for new items;
  • Regularly check my podcast feeds and automatically download anything new;
  • Build playlists to a fairly specific logic (more on this later);
  • Sync a defined subset of my media to my phone.

To a greater or lesser extent all of the applications I tried were able to cover most of what I wanted but none of them could do all of it in the way I wanted it to work. After kludging along for a few weeks and jotting down my thoughts for how I wanted it to work, I decided to write a set of bash scripts to do it all for me. For those not familiar with bash scripting, it is not dissimilar in concept to the old MS-DOS batch file; a list of terminal commands.

Let’s talk in a little more detail about how I organise my playlists. For years I worked with hand crafted playlists, by album, artist, genre, etc. Then I read a great post at about an alternative way of using smart playlists. What I came up with was this set of playlists:

  • Gems – Around 300 of my favourite tracks that I always want to have available on my device. These were denoted by a rating of 4 or more stars;
  • Interesting – A random selection of around 400 tracks of the albums and artists that I particularly like. These were denoted by a rating of 3 stars;
  • Random – Somewhere in the region of 200-400 tracks plucked at random from the rest of my media library. I vary this number depending on how much space I want to leave available on the device.

One key point to note is that there are a fair number of tracks in my media library that I don’t want to listen to. Of course you could argue that I could just delete them, but I’m a bit of a completist, and it just feels wrong to have, say, all of Stevie Wonder’s Definitive Collection album but to delete “I Just Called To Say I Love You”.

I got round this by flagging all of these tracks with 1 star and then excluding them from all of the randomly selected playlists.

Ok so let us get on to the scripts that I wrote. They are;

  • CheckAndDownloadPodcasts;
  • RebuildPlaylists (which for each mp3 calls AddToPlaylist);
  • PhoneSync.

CheckAndDownloadPodcasts uses a command line utility called hpodder. The script is run every two hours using cron and does exactly what it says on the tin. In addition, one of my favourite podcasts is only available in the UK. I wanted to share this with a friend in the US so everytime a new episode is downloaded the script automatically copies it across to a shared Dropbox folder. Job done.

RebuildPlaylists is the one that really took the time. My first challenge was that, in the mp3 file’s tags (the id3 tag) there is no standard way of representing the rating value. I got round this by using an alternative field; the comment. This is free format text. I flag all of the relevant tracks with the text “gem”, “interesting”, “grim” or blank. The script then runs through the whole of my media library and adds tracks to the relevant playlist. For those that are randomised and truncated, it pipes the playlist into a “sort -R” to randomise it, then to “head -n 300” to cut it to 300 tracks.

PhoneSync uses the fantastic rsync command line utility to copy all of the tracks over to the phone (or another media device). One of the great things about rsync is that it compares source and destination and only copies the file if there are differences. My script uses the “–delete” option so that it tidies up the old tracks no longer required. For the first few weeks of use I was happily syncing just my music, until I realised that this script could do a bit more. Now it backs up all of the pictures and videos I’ve taken with my phone and syncs with a document library on my laptop, so that I can always make sure I have copies of some key documents with me, or indeed that any documents I update when I’m out and about find their way back on to my laptop.

If you want to look through my scripts in more detail you can see them below, but please be aware, they are just built for me, to work with my directory structures, with a lot of my own logic hard-coded. If you want to make use of them you’ll have to amend for your own circumstances.


#! /bin/bash
# fetch latest podcasts
hpodder fetch
# set genre to "101" for "Speech"
find /home/davmac/podcasts -name '*.mp3' -exec id3v2 -g 101 {} \;
# copy to Dropbox for Larry
find /home/davmac/podcasts -name '*joy*.mp3' -exec cp {} /home/davmac/Dropbox/DaveLarryShare \;


#! /bin/bash
# delete existing playlists
rm /home/davmac/Music/*.m3u
# find all mp3s and add to the relevant playlists
find /home/davmac/Music -name '*.mp3' -exec /home/davmac/Applications/scripts/AddToPlaylist {} \;

# sort, randomise and cutdown where relevant
cat /home/davmac/Music/gem.m3u | sort -R | head -n 300 | sort > /home/davmac/Music/gems.m3u
cat /home/davmac/Music/int.m3u | sort -R | head -n 400 | sort > /home/davmac/Music/interesting.m3u
cat /home/davmac/Music/rnd.m3u | sort -R | head -n 200 | sort > /home/davmac/Music/random.m3u
rm /home/davmac/Music/rnd.m3u
rm /home/davmac/Music/int.m3u
rm /home/davmac/Music/gem.m3u


#! /bin/bash
case `mp3info -p "%c" /"$1"` in
		echo $1 >> /home/davmac/Music/gem.m3u ;;
		echo $1 >> /home/davmac/Music/int.m3u ;;
		echo $1 >> /home/davmac/Music/rnd.m3u ;;


#! /bin/bash
if [ -d /media/867B-0D15 ] ; then
	# sync stuff from laptop to phone
	rsync -vrut --delete /home/davmac/podcasts /media/867B-0D15
	rsync -vrut --delete --files-from=/home/davmac/Music/gems.m3u / /media/867B-0D15/Music
	rsync -vrut --delete --files-from=/home/davmac/Music/interesting.m3u / /media/867B-0D15/Music
	rsync -vrut --delete --files-from=/home/davmac/Music/random.m3u / /media/867B-0D15/Music
	# sync stuff from phone to laptop
	rsync -vrut /media/867B-0D15/Documents /home/davmac/Documents/android
	rsync -vrut /media/867B-0D15/DCIM /home/davmac/Pictures/android
exit 0

Leave a Reply

Please log in using one of these methods to post your comment: 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