初歩のシェルスクリプトで遊ぶ[md5チェックサムのファイル書式を変換]
Name MD5 Bytes --------------------------------------------------------------- -------------------------------- --------- omake\nukamiso-doc_beta13_changelog.txt 44bab025a725a77604ecdacea076c899 18,809 omake\nukamiso-doc_beta13_license.txt 8bd736f50d06dce0694a4fbdc83f46ae 13,954 omake\nukamiso-doc_html-assets\css_edelweiss.css d1a11d06b9a457311f94370bd5d9941d 4,251 --- 中略 ---- omake\nukamiso_konbu_beta13_0.ttf b9ff8a4615e43033c72442e4cb16a344 3,427,932 omake\nukamiso_otf_beta13_0.otf c2387173f3cff4c803276cf9d803498d 3,693,508 omake\nukamiso_yamiyo_beta13_0.ttf 0dc9cbf3b76eb0f46b0e9a4add67dc1a 3,758,008 omake\nukamiso__beta13_0.ttf 191b368a3398d710ef991e9a2e69e698 4,227,404 rnd.css 8af3a7d33be50a132cf1d1a920c5a826 2,587 ------------------------------------------------------------------------------------------------------------ Total 40 Files 33,387,437 Bytes
ぬかみそフォントに同梱している、zipファイルに含まれる中身のリストです。
FastHashの詳細情報 : Vector ソフトを探す!
これはWindows用の『FastHash』というソフトで作ってます。形式としては「WinCRC」というソフトに準じてるんだそうですが、そっちのほうは私は知りません。
このチェックサムファイルはWindows用ですから、Linuxのmd5sumでは使えません。
Linuxのmd5sumが出力する形式は、ファイル名とmd5値のみがあればよく、ファイルサイズは要りません。
md5sumの出力をWindowsのWinCRC形式に変換するのは情報が足りませんが、md5sum形式への変換なら、文字の並び替えでできます。
簡単なスクリプトでmd5sum用に変換できるんじゃないかな、と思ってたんだけれども、案外めんどくさかった。
#!/bin/sh # ==================================================================================== # ■ winCRC形式チェックサムファイルを、Linuxのmd5sum用に書き換える # # ・実際に使うのはwin FastHash の生成データ # ・入力はCP932,CRLFのテキストデータ,stdin 1ファイルずつのみ # ・出力はstdoutのみ、ファイルは作らない # # ・md5とsha256に対応する # ・空白文字がファイル名に入っても処理できる # # ・nkfを使ってはならない # ・dos2unixを使ってはいけない # # # # ==================================================================================== headerFooterCrDelSh(){ ( CR="`printf '\015'`" while read -r LINE ; do # 行末のCRを削除 LINE="${LINE%${CR}}" # 行末が「-」または「Bytes」の行を削除 case "${LINE}" in ( *'-' | *'Bytes' ) continue ;; esac # echoでは駄目 dashで「\」がエスケープ扱いされるため printf '%s\n' "${LINE}" #echo "${LINE}" # 【debug】 done ) } fileSizeDelSh(){ ( while read -r LINE ; do # 行末のファイルサイズ部分を削除 # 行末から半角空白が最初に出現するまでを消去する LINE="${LINE% *}" # 行末の連続空白を削除する LINE="${LINE%${LINE##*[! ]}}" # 行末の連続空白を削除する_whileとcase #while true ; do #LINE="${LINE% }" #case "${LINE}" in #( *' ' ) #continue #;; #( * ) #break #;; #esac #done printf '%s\n' "${LINE}" done ) } filePathXsumSh(){ ( # ファイルパス checkSum # ↓ # checkSum *ファイルパス while read -r LINE ; do # 「ファイルパス+半角空白連続-1個」部分を抽出 filePath="${LINE% *}" # 「半角空白1個+チェックサム」部分を抽出 checkSum="${LINE#${filePath}}" # 先頭半角空白を削除 checkSum="${checkSum# }" # ファイルパス末尾の連続半角空白を削除 filePath="${filePath%"${filePath##*[! ]}"}" #printf '%s\n' "${LINE}" # 【debug】 #printf '\033[7m%s\033[0m\n' "${filePath}" # 【debug】 #printf '\033[7m%s\033[0m\n' "${checkSum}" # 【debug】 # 「 *」を挟んで出力 printf '%s *%s\n' "${checkSum}" "${filePath}" done ) } # iconvから処理を開始すること if stdinTemp="`iconv -f cp932 -t utf8`" then true else exit 1 fi printf '%s\n' "${stdinTemp}" | tr '\\' '/' | headerFooterCrDelSh | fileSizeDelSh | filePathXsumSh
外部コマンドは文字コード変換用のiconvと、Windowsのディレクトリ区切りの「\」をLinuxの「/」へ変換するtrです。他はシェルの基本機能で済ませてます。
シェルの変数展開を多用してるのが特徴です。
意外とめんどくさい題材
cutやawkで切り貼りすれば簡単にできるかな、と思ってたんですが、あんまりコマンドとは相性がよくなくて、cut等で組んだ試作品は不格好になりました。
- Windowsのファイルパスでも半角空白文字は普通に使われる。「半角空白は使わないでね」というわけにもいかない。
- cutコマンドでは「左から1番目」「左の2番目から3番目」という指定はできるが、「最後の1番目」が難しい。ファイルパスに半角空白が入ると、cutコマンドではフィールド番号がずれてしまう。
- revコマンドで左右をひっくり返してからcut、という手もあるが、これは日本語を含んだ文字列をrevコマンドでちゃんと使えることが前提になる。やってみたらできてはいたけれど……。