BashPodder mod – add podcasts to iTunes

As a podcatcher (among other things), iTunes sucks. Badly. iPodder is nicer, mainly because I can keep my follow list in the cloud at PodNova. However, it (or the combination with podnova) often ends up downloading gigs of old stuff, on some particular feeds. Worse, it consumes obscene quantities of memory and CPU, with its UI being unresponsive to the point of being unusable, like 30 second or more delays for each gesture. This is on an early macbook.

Anyway, I decided to rectify the situation and go back to bashpodder, a tiny shell script which proves the point that a podcatcher need not be grandiose, nor a resource gobbler. It’s also cool as it’s easily customisable for anyone with some bash-fu. I modded it a few years back to keep my follow list in the cloud. (I believe clouds were called “servers” back then.)

I’ve recently modded bashpodder to add files to iTunes. Yes, I still like iTunes and I definitely like the i* players which are, for most intents and purposes, constrained to the universe of iTunes. As for it’s podcatcher, not cool. The interface for exploring podcasts is cumbersome, and the result, the downloaded podcasts, are not handle with care. For example, if you download podcasts with iTunes, it marks them out specially as podcasts, and there’s no way to, say, delete all podcasts older than a week. If they’re normal tracks added from an external catcher, they’re just regular MP3s and you can do what you like with them. And you can’t keep your follow list in the cloud!

So here’s bashpodder modified to add to itunes. (The itunes part I added is the HERE doc section beginning with /usr/bin/osascript. You could easily extend it to, say, tag podcasts from certain feeds with a certain album name.)

Click on “Plain Text” and cut-and-paste it into a shell file. Easiest would be to download the several files required for bashpodder (there should be a mod to make it just a single self-modifying file), and replace contents with that below.


  1. #!/bin/bash
  2. # By Linc 10/1/2004
  3. # Find the latest script at
  4. # Revision 1.2 09/14/2006 - Many Contributers!
  5. # If you use this and have made improvements or have comments
  6. # drop me an email at linc dot fessenden at gmail dot com
  7. # I'd appreciate it!
  9. # Make script crontab friendly:
  10. cd $(dirname $0)
  12. # datadir is the directory you want podcasts saved to:
  13. datadir=$(date +%Y-%m-%d)
  15. # create datadir if necessary:
  16. mkdir -p $datadir
  18. # Delete any temp file:
  19. rm -f temp.log
  21. # Read the bp.conf file and wget any url not already in the podcast.log file:
  22. while read feed
  23.   do
  24.   podcast=`echo $feed | cut -f 1 -d ' '`
  25.   echo $podcast
  26.   file=$(xsltproc parse_enclosure.xsl $podcast 2> /dev/null || wget -q $podcast -O - | tr 'r' 'n' | tr ' " | sed -n 's/.*url="([^"]*)".*/1/p')
  27.   for url in $file ; do
  28.     echo "Retrieving $url"
  29.     echo $url >> temp.log
  30.     if ! grep "$url" podcast.log > /dev/null
  31.       then
  32.       # wget -t 10 -U BashPodder -c -q -O $datadir/$(echo "$url" | awk -F'/' {'print $NF'} | awk -F'=' {'print $NF'} | awk -F'?' {'print $1'}) "$url"
  33.       outpath=$datadir/$(echo "$url" | awk -F'/' {'print $NF'} | awk -F'=' {'print $NF'} | awk -F'?' {'print $1'})
  34.       curl --retry 10 -C - $url > $outpath
  35.       fullpath=`pwd`/"$outpath"
  36.       /usr/bin/osascript <<-EOF
  37.         tell application "iTunes"
  38.           set posix_path to "$fullpath"
  39.           set mac_path to posix_path as POSIX file
  40.           set new_track to add mac_path
  41.           set genre of new_track to "*Podcast"
  42.         end tell
  43. EOF
  44.     fi
  45.     done
  46.   done < bp.conf
  47. # Move dynamically created log file to permanent log file:
  48. cat podcast.log >> temp.log
  49. sort temp.log | uniq > podcast.log
  50. rm temp.log
  51. # Create an m3u playlist:
  52. ls $datadir | grep -v m3u > $datadir/podcast.m3u

Man pages that read more like legal contracts

Case in point: I want to use “find” to find files I’ve recently created.

man find (BSD edition):

-ctime n[smhdw] If no units are specified, this primary evaluates to true if the difference between the time of last modification time and the time find was started, rounded up to the next full 24-hour period, is n 24-hour periods.

If units are specified, this primary evaluates to true if the difference between the time of last modification time and the time find was started is exactly n units. Please refer to the -atime primary description for information on supported time units.

Humane documentation FAIL! The precision here is all well and good to include somewhere, but unnecessary for most usages. Please, just tell me what I need to know and Don’t Make Me Think!.

What I wanted to see:

-mtime t

Include only files modified t days ago. You will typically want to specify a +/- sign. e.g. “-ctime +3” for files created 3 or more days ago. To measure in another unit of time, you can append one of the following to t: s for seconds, m for minutes, h for hours, d for days, w for weeks, but note that “-ctime” unfortunately only works if the time is at least one day. For example, “find . -ctime 1d6h” will return files created in the past 30 seconds.

Technical detail: (the legalese stuff goes here. 99% of users will never need it and never read it.)

The improved version focuses on what the typical user needs to know, uses active voice, avoids the cross-reference (it’s documentation, not code, so embrace redundancy!), and most importantly, includes an example. (The man page does include examples at the bottom, but (a) they should be included against each component too; and (b) they still shy away from concrete values: “-newer ttt”!!!)

A lot of these man pages have been around for two decades or more, with minimal changes to my knowledge; I’d love to see someone like Ubuntu sponsor an effort to bring them up to date. Plain English without dumbing down.

SSH Tip: Remember Last Path

ssh, Unix

Lately, I’ve been living dangerously and doing a lot of coding on the live server, via ssh. This is all proof-of-concept stuff at Ajaxify. The reason I’m coding live is that it’s all widget development and it’s just easier that way, since environments like iGoogle and Facebook need to reach my apps live, in order to test the app. None of the alternatives take my fancy: open up a port into my development PC (difficult due to dynamic DNS and less secure); upload code each change (slow even if it’s fully scripted); use Shindig on my local machine (unreliable as Shindig is new and in rapid growth mode).

So I’ve been ssh’ing and no matter how many times I’ve tried, I can’t remove ssh timeout, so I sometimes get timed out. So anyway, I wanted an easy way to remember the most recent directory I was in, each time I log back in. This is it – in my .bash_profile:

function cd { builtin cd $1 ; pwd > $HOME/.path_history; }
cd cat $HOME/.path_history

Documentation Needs Examples (Duh)

I’m constantly amazed at the amount of documentation people are inclined to create without including a single example.

Man pages that devote pages worth of command-line options, flags, grammar, caveats, historical anecdotes, and NOT A SINGLE EXAMPLE.

Textbooks that devote pages to a particular API, then expose it all in one monolithic program.

Countless reference documentation on HTML tags and CSS grammar, and NOT A SINGLE EXAMPLE.

In a world where free videos make it stupidly obvious how to kickstart your lawmowing experience and watching a screencast precedes the creation of “Hello World” in any language you care to adopt, let’s get it straight: An example says a thousand words.