いろんなアーカイブを展開できるコマンド

30分プログラム、その567。いろんなアーカイブを展開できるコマンド。
ターミナルでアーカイブを展開するには、それぞれコマンドを変えないといけない。例えばば、hoge.tar.gzなら、"tar xvzf hoge.tar.gz"、hoge.zipなら"unzip hoge.zip"みたいな感じに。

でも、ダブルクリックすればなんでもできる世界に暮してきたボクらには、これはちょと厳しい。というわけで、いろんなアーカイブを展開できるコマンドを書いてみた。

拡張子やMIMEタイプに基づいて実行するコマンドを切り替えている。あと、何気に始めて__END__を使ってみた。

使い方

$ unpack caml2html-1.3.0.tar.bz2
>>> tar xvjf caml2html-1.3.0.tar.bz2
caml2html-1.3.0/
caml2html-1.3.0/META
caml2html-1.3.0/TODO
caml2html-1.3.0/caml2html_test.ml
....
$ unpack SWFUpload_v2.0.2.Release.zip
>>> unzip -d SWFUpload_v2.0.2.Release SWFUpload_v2.0.2.Release.zip
Archive:  SWFUpload_v2.0.2.Release.zip
....

ソースコード

#! /usr/bin/env ruby
# -*- mode:ruby; coding:utf-8 -*-
#
# unpack.rb -
#
# Copyright(C) 2009 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2009/04/16 20:58:04
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#

module Enumerable
  def any(&f)
    self.each do|item|
      x = f.call item
      return x if x
    end
    return nil
  end
end

class App
  def initialize
    @cmds = []
    instance_eval DATA.read
  end

  def ext(ext,&f)
    @cmds << lambda{|file|
      if file =~ /#{Regexp.quote ext}\Z/ then
        f.call file
      end
    }
  end

  def mime(mime,&f)
    @cmds << lambda{|file|
      if %x(file -bI #{file}).chop == mime then
        f.call file
      end
    }
  end

  def unpack(files)
    files.each do|file|
      cmd = @cmds.any{|f| f.call file}
      abort("unknown file type: #{file}") unless cmd
      puts ">>> #{cmd}"
      system cmd
    end
  end
end

App.new.unpack(*ARGV)

__END__
# 拡張子による指定
ext '.tar.bz2' do|file|
  "tar xvjf #{file}"
end

ext '.tar.gz' do|file|
  "tar xvzf #{file}"
end

# mimeタイプによる指定
mime 'application/x-zip' do|file|
  t = File.basename file,".*"
  "unzip -d #{t} #{file}"
end