Export iTunes playlist songs to an external location (SD Card)
The majority of the time I use my iPhone to play music in my car via USB or Bluetooth. Recently I decided to utilize the SD card slot as well and fill one with MP3s. I soon realized iTunes does not have an easy way of exporting music to an SD card, so I wrote a simple Ruby script to do so.
I created a smart playlist based on my genres and ratings called “Jeep”. I then exported this playlist as plain text via:
File > Library > Export Playlist...
  - Save as: Jeep.txt
  - Format: Plain TextI created a Yaml configuration file (config.yml):
---
playlist_path: ./Jeep.txt
export_path: /Volumes/ERLJEPMUSIC
output_parts:
- Artist
- Album
- Track Number
- Name
output_delimiter: " - "I created the following Ruby script to load the config.yml file, parse the exported playlist as plain text, create an export path for each file, and then copy the files to the destination.
#!/usr/bin/env ruby
require 'set'
require 'yaml'
class ItunesFileExporter
  def initialize
    @songs = Set.new
    @headers = nil
    load_config
    playlist_to_hash
  end
  def run
    copy_files
  end
  private
  def load_config(config_path = './config.yml')
    @config = YAML.load_file(config_path)
  end
  def playlist_to_hash
    File.readlines(@config['playlist_path'], "\r").each do |line|
      cols = line.strip.split("\t")
      if @headers.nil?
        @headers = cols
      else
        @songs << song_data(cols)
      end
    end
  end
  def song_data(cols)
    hsh = Hash[@headers.zip(cols)]
    file_extension = hsh['Location'].split(/\./).last
    hsh['Location'] = hsh['Location'].tr(':', '/').gsub(/^Macintosh HD/, '')
    file_parts_joined = @config['output_parts']
                        .each_with_object([]) { |part, arr| arr << hsh[part] }
                        .join(@config['output_delimiter'])
                        .tr('/', '_')
    hsh['_output_path'] = "#{@config['export_path']}/#{file_parts_joined}.#{file_extension}"
    hsh
  end
  def copy_files
    @songs.each do |song|
      puts "Copying: #{song['_output_path']}"
      if File.exist?(song['_output_path'])
        puts 'File already exists.'
        next
      end
      FileUtils.cp(song['Location'], song['_output_path'])
    end
  end
end
ItunesFileExporter.new.run