Windowsで作ったZIPファイルに日本語ファイル名やフォルダを含めると、UTF-8環境では化けます。その逆にUTF-8環境で作ったZIP日本語ファイルはWindowsで化けます。
文字化けさせずに取り出す。
文字化けさせない方法は色々あるがRubyでぱぱっと書くのが一番楽。
find -name "*.zip" -print0 | xargs -0 -I_ ./unzip.rb _
unzip.rb
(2011-09-07 追加 以下コードの最新版をこのエントリの末尾に追加)
#!/usr/bin/env ruby # zipruby が必須 require 'rubygems' require 'zipruby' require 'fileutils' require 'kconv' OUTPUT_DIR = "./out/" FileUtils.mkdir_p(OUTPUT_DIR) unless File.exist?(OUTPUT_DIR) ZIPFILE_NAME = ARGV.first Zip::Archive.open(ZIPFILE_NAME){ |entries| entries.each{|entry| name = entry.name.toutf8.gsub("\\", "/") if entry.directory? FileUtils.mkdir_p(OUTPUT_DIR+name) else dirname = File.dirname(name) FileUtils.mkdir_p(OUTPUT_DIR+dirname) unless File.exist?(OUTPUT_DIR+dirname) open(OUTPUT_DIR+name, "wb") do|f| f << entry.read end end } }
rubyの場合ziprubyを使う
zipruby と rubyzip と二つあるが、rubyzipはJava脳の人が書いたJAVAっぽいメソッド。こまります。作者もjavaのZIP設計を移植したと描いている。Rubyから使いづらい。なのでZipRubyを使います。
findコマンドの解説
find コマンドでzipファイル探してxargsで展開してunzip.rbに渡します。
find -name "*.zip" # *.zip にマッチするファイルをカレントディレクトリ以下で探す -print0 # ファイルの区切りに空白を使わない(ファイルに空白が含まれる場合)
xargs
xargs -0 # find -print0 を受け取るときはこう書く -I_ # findから受け取ったファイル名は _ とする ./unzip.rb _ # _ にfindから受け取ったファイル名を代入してコマンド実行
find / xargs 便利ですね。
WindowsのSJISで書かれたZIPを取り出す。そのほかの方法
WindowsのSJISで書かれたZIPをLinuxから扱うには他にも色々方法がありました。
そのほかの方法
コマンドからだと次の方法で何とかなる。
export LANG=C 7z x -o../out test.zip convmv -r --notest -f cp932 -t utf-8 export LANG=ja_JP.UTF8
ただし、これはディレクトリ階層が入っているとうまくいかない。ディレクトリ区切り文字"\"が原因で、誤動作している気がする。
2011-06-15追記
この逆でLinuxからWindows用に,Zip作る場合はこっち
rubyでWindows(sjis)用のZIPファイルを作る。 - ブックマクロ開発に
2011-09-07 追記
出力ファイルフォルダを入力ファイルと同じにした
./unzip.rb test.zip # ./test/に展開される
ls *.zip | xargs -I@ ./unzip.rb @
#!/usr/bin/env ruby # zipruby が必須 require 'rubygems' require 'zipruby' require 'fileutils' require 'kconv' ZIPFILE_NAME = ARGV.first OUTPUT_DIR = "./" + File.basename(ZIPFILE_NAME,File.extname(ZIPFILE_NAME)) + "/" FileUtils.mkdir_p(OUTPUT_DIR) unless File.exist?(OUTPUT_DIR) Zip::Archive.open(ZIPFILE_NAME){ |entries| entries.each{|entry| name = entry.name.toutf8.gsub("\\", "/") if entry.directory? FileUtils.mkdir_p(OUTPUT_DIR+name) else dirname = File.dirname(name) FileUtils.mkdir_p(OUTPUT_DIR+dirname) unless File.exist?(OUTPUT_DIR+dirname) open(OUTPUT_DIR+name, "wb") do|f| f << entry.read end end } }