Skip to content

Instantly share code, notes, and snippets.

@stevebrun
Last active November 12, 2015 08:34
Show Gist options
  • Save stevebrun/90c77f9af6824172c05a to your computer and use it in GitHub Desktop.
Save stevebrun/90c77f9af6824172c05a to your computer and use it in GitHub Desktop.
Command line utility to convert an ISBN to a Library of Congress Column Number
#!/usr/bin/osascript
on printLCCN(LCCN)
tell application "DYMO Label"
set paperOrientation to portrait
tell print object 1
set object text to LCCN
end tell
printLabel2 of it
end tell
end printLCCN
-- taken from https://geert.vanderkelen.org/2010/splitting-as-string-and-joining-a-list-using-applescript/
to joinList(aList, delimiter)
set retVal to ""
set prevDelimiter to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set retVal to aList as string
set AppleScript's text item delimiters to prevDelimiter
return retVal
end joinList
on run argv
if (count of argv) is not 0 then
my printLCCN(joinList(argv, "\n"))
end if
end run
#! /usr/bin/env ruby
require 'open3'
iccn_list = if (ARGV.empty?) or (ARGV[0] == '-f' || ARGV[0] == '--file') then
ARGV.shift if not ARGV.empty?
ARGF
else
ARGV
end
begin
iccn_list.each do |isbn|
lccn = `./isbn2lccn.rb #{isbn}`
`./dymoPrintLCCN.applescript #{lccn}`
puts lccn
end
rescue Interrupt => e
end
#!/usr/bin/env ruby
require 'open3'
class YazConnection
# reference: http://www.xml.com/pub/a/2004/06/02/dijalog.html
# reference: http://www.indexdata.com/yaz/doc/yaz-client.html
# reference: http://lists.indexdata.dk/pipermail/yazlist/2006-July/001668.html
# reference: https://gist.github.com/toroidal-code/6415977
# you can install the yaz-client command with `brew install yaz`,
# or you can visit http://www.indexdata.com/yaz/
attr_accessor :stdin, :stdout, :stderr
def initialize(server='z3950.loc.gov:7090/voyager')
self.stdin, self.stdout, self.stderr =
Open3.popen3('yaz-client', server)
# this is the URL, port, and datavase that everyone else uses
self.read_response_lines {|x|}
end
def close
self.stdin.close
self.stdout.close
self.stderr.close
end
def readprompt
3.times { self.stdout.readchar } # reads 'Z> '
end
def read_response_lines
reading_is_done = false
until reading_is_done
line = self.stdout.readline
begin
if line.split(':')[0] == 'Elapsed' then
reading_is_done = true
else
yield line
end
rescue => exception
STDERR.puts exception
end
end
self.readprompt
end
def readmarc
3.times { self.stdout.readline }
lines = []
self.read_response_lines { |l| lines << l }
Marc.new(lines)
end
def fetch_lccn(isbn)
self.stdin.puts "find @attr 1=7 #{isbn.gsub('-', '')}"
# the search query to find entries with that isbn
# from what I can tell, 1 means 'use this', and 7 means 'ISBN field'
3.times { self.stdout.readline }
line = self.stdout.readline
results = line.sub('Number of hits: ', '').to_i
2.times { self.stdout.readline }
self.readprompt
return nil unless results > 0
self.stdin.puts "s 1" # request a USMARC result
return self.readmarc.lccn
end
end
class Marc
attr_accessor :lccn
def initialize(lines)
lines.each do |line|
self.lccn = LCCN.new(line) if LCCN.LCCN_line? line
end
end
end
class LCCN
# reference: http://www.loc.gov/marc/authority/ad050.html
attr_accessor :classification, :item, :volumes, :institution, :loc_official
def self.LCCN_line? (line)
line[0..2] == '050' # the infamous line 050 is where the LCCN is stored
end
def initialize(line050)
fields = line050[4..-1].split('$') # the line begins '050 '
self.loc_official = (fields[0][1].to_i == 0)
# the format is '0#' where # is either 0 or 4
fields = Hash[ fields[1..-1].map { |field| [field[0], field[2..-1].strip] } ]
self.classification = fields['a']
self.item = fields['b']
self.volumes = fields['d']
self.institution = fields['5']
end
def loc_official?
self.loc_official
end
def to_s
fields=[self.classification, self.item, self.volumes, self.institution]
string = fields.select { |x| not x.nil? }.join ' '
lccn_regexp = /(^[A-Z]*) *([0-9]*.[0-9]+) *(.[A-Z]*[0-9]*) *(.[A-Z]*[0-9]*) *([0-9]*)/i
string.match(lccn_regexp).captures.map {|x| x.strip }.join ' '
end
end
# command line script starts here
yaz = YazConnection.new
isbn_list = if (ARGV.empty?) or (ARGV[0] == '-f' || ARGV[0] == '--file') then
ARGV.shift if not ARGV.empty?
ARGF
else
ARGV
end
begin
isbn_list.each do |isbn|
lccn = yaz.fetch_lccn isbn
if lccn.nil? then
# servers from http://isbnsearch.sourceforge.net/servers.html
more_servers = ['albert.rit.edu:210/innopac',
'aleph.mcgill.ca:210/muse',
'catalog.bedfordlibrary.org:210/innopac',
'catalog.library.cornell.edu:7090/voyager',
'catalog.library.colostate.edu:210/innopac',
'catalog.mbln.org:210/horizon',
'catalog.princeton.edu:7090/voyager',
'catalog.wustl.edu:210/innopac',
'clio-db.cc.columbia.edu:7090/voyager',
'grammy.mit.edu:9909/mit01']
while lccn.nil? && (not more_servers.empty?)
server = more_servers.shift
# STDERR.puts "trying #{server}"
yaz_c = YazConnection.new(server)
lccn = yaz_c.fetch_lccn isbn
yaz_c.close
end
end
puts lccn
end
rescue Interrupt => e
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment