初歩のシェルスクリプトで遊ぶ[ファイルのリネームツール、のようなもの?_(1)]

名前は「burdock」

シェルスクリプトでファイルのリネームツールを作って……作れたのかなぁ。リネームできてるっちゃあできてますが、画像の形式変換だとかもできちゃうんすけど……。

環境とか注意とか

Ubuntu18.04 VirtualBox6.1.8_GNU bash, バージョン 4.4.20(1)-release (x86_64-pc-linux-gnu)

  • 連想配列が使えるbash専用です。
  • 仕様上、rmだろうとrebootだろうと使えます。事故に注意。
  • 使うのは誰でも自由ですが、バグはもちろん事故も十分にありえるので、そのへんは了承してください。私は責任は持てません。

使用例

1.写真ファイルからexif情報を取り出してリネーム_端末用インターフェースから

(途中でテキストファイルを編集する必要あり)

  1. (--once)1ファイル1実行モードに変更し、
  2. (--data-load)テキストファイルをこのスクリプトが読み込んでシェル変数に格納、
  3. (_suffix,中身はsed)名前と拡張子の間に変数で指定したテキストデータを書き込んで、
  4. (--ext)拡張子編集モードに変更し、
  5. (_small,中身はtr)拡張子を小文字に変換する。


2.ファイルに乱数のサフックスをつけてリネーム_コマンドラインから
  1. シェル変数モードに変更し、
  2. コマンド実行モードを1ファイル1実行モードに切り替え、
  3. サフックスにBash組み込み変数の${RANDOM}を、1ファイルにつき1回展開しながら付加する。
$ ls | burdock --shell --once '_suffix "_${RANDOM}"'
cd -- "/media/sf_003" ;  mv -n -v -- 'diary.txt' 'diary_30078.txt' ; 
cd -- "/media/sf_003" ;  mv -n -v -- 'image.jpg' 'image_3938.jpg' ; 
cd -- "/media/sf_003" ;  mv -n -v -- 'memo.txt' 'memo_13931.txt' ; 
cd -- "/media/sf_003" ;  mv -n -v -- 'picture.jpg' 'picture_9382.jpg' ; 

コマンドライン版の中核スクリプトのみ

と、けっこう量があるんで、どうやるべかと。
プログラマーの世界だと常識な方法とかあるんでしょうけど、私にゃ分からんので、あとでzipで出します。フォントと同じところにでも。
スクリプト1枚で動く中核部分だけ置いときます。もう基本仕様は変わらんと思うから。
ユーザインターフェースのほうは、まだ書き換えが激しくて。公開してもすぐ消しちゃいそうなんす。

続きを読む

初歩のシェルスクリプトで遊ぶ[シフトJISをutf8に変換-4,メガネハナーンの切れ端からガリバー旅行記を組み立てる]

調べものには使えません。
Ubuntu18.04,Virtualbox6.1.2,dash,bash

シフトJISテキストファイル→utf8の16進数→utf8テキストファイル

スクリプトは後に置いとくとして、作ったスクリプトを通して動かします。
あらためて方針を説明。

  • Windowsのテキストファイル(cp932)を、Linux環境で読めるようにしたい。
  • 出発はodコマンドのダンプ。
  • ただし、妥協はする。
  • 不具合があっても、読めればよし。
  • 最低限の簡易型でいい。
  • 趣味で個人が読むテキストファイルを変換するのに、十分な変換速度は目指す。
  • 処理の無駄を省くよりも、回り道することを優先する。
妥協点
  • 辞書ファイルを作るときに、iconvコマンドを使った
  • 辞書ファイルを作るときに、xxdコマンドを使った

xxdコマンドを使わなくても、任意のバイナリデータを作れる、ということは示したので、下のスクリプトではxxdコマンドにしてます。
メガネハナーンバイナリ作成機の使用例も兼ねて、参考にcp932の文字リスト(7882文字)を、ダンプリストからテキストファイルに変換した結果。

$ cat cp932dump.txt | head
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39
3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53
54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D
6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E A1 A2 A3 A4 A5 A6 A7 A8 A9
AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3
C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD
DE DF
8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 814A 814B 814C 814D 814E 814F
8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 815A 815B 815C 815D 815E 815F
8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 816A 816B 816C 816D 816E 816F
$ time 0< cp932dump.txt dash ./binCreator_02.sh >cp932txt_hananegane.txt
real	0m0.349s
user	0m0.083s
sys	0m0.220s
$ time 0< cp932dump.txt xxd -r -p >cp932txt_xxd.txt
real	0m0.004s
user	0m0.002s
sys	0m0.001s
$ md5sum cp932txt_*
50ca0b7bc00087c8ea64581da94625a8  cp932txt_hananegane.txt
50ca0b7bc00087c8ea64581da94625a8  cp932txt_xxd.txt
$ cat cp932txt_hananegane.txt | iconv -f cp932 | cut -c 1-2100
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚ 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪†‡¶◯0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇

できてますね。

ガリバー旅行記』を通して変換してみる

図書カード:ガリバー旅行記

$ 0< gulliver_ryokoki.txt ./sjisTextToUtf8Code02.sh | head
 e3 82 ac e3 83 aa e3 83 90 e3 83 bc e6 97 85 e8 a1 8c e8 a8 98 0a 47 55 4c 4c 49 56 45 52 27
 53 20 54 52 41 56 45 4c 53 0a e3 82 b8 e3 83 a7 e3 83 8a e3 82 b5 e3 83 b3 e3 83 bb e3 82 b9
 e3 82 a4 e3 83 95 e3 83 88 e3 80 80 4a 6f 6e 61 74 68 61 6e 20 53 77 69 66 74 0a e5 8e 9f e6
 b0 91 e5 96 9c e8 a8 b3 0a 0a 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
 2d 2d 2d 0a e3 80 90 e3 83 86 e3 82 ad e3 82 b9 e3 83 88 e4 b8 ad e3 81 ab e7 8f be e3 82 8c
 e3 82 8b e8 a8 98 e5 8f b7 e3 81 ab e3 81 a4 e3 81 84 e3 81 a6 e3 80 91 0a 0a e3 80 8a e3 80
 8b ef bc 9a e3 83 ab e3 83 93 0a ef bc 88 e4 be 8b ef bc 89 e3 83 9c e3 83 bc e3 83 88 e3 82
 92 e6 bc 95 e3 80 8a e3 81 93 e3 80 8b e3 81 90 0a 0a ef bd 9c ef bc 9a e3 83 ab e3 83 93 e3
 81 ae e4 bb 98 e3 81 8f e6 96 87 e5 ad 97 e5 88 97 e3 81 ae e5 a7 8b e3 81 be e3 82 8a e3 82

青空文庫のテキストファイルを読ませると、16進数をダーッと出力します。
まず単体で測定。次に、パイプで繋いで実行します。

$ time 0< gulliver_ryokoki.txt ./sjisTextToUtf8Code02.sh 1>/dev/null
real	0m6.121s
user	0m4.461s
sys	0m2.333s
$ time 0< gulliver_ryokoki.txt ./sjisTextToUtf8Code02.sh 1>gulliver_dump.txt
real	0m6.272s
user	0m4.951s
sys	0m1.995s
$ time 0< gulliver_dump.txt ./binCreator_02.sh 1>/dev/null
real	0m5.029s
user	0m2.082s
sys	0m2.822s
$ time 0< gulliver_ryokoki.txt ./sjisTextToUtf8Code02.sh | ./binCreator_02.sh 1>/dev/null
real	0m11.066s
user	0m6.830s
sys	0m4.655s
$ 0< gulliver_ryokoki.txt ./sjisTextToUtf8Code02.sh | ./binCreator_02.sh 1>gulliver_ryokoki_hanamegane.txt
$ 0< gulliver_ryokoki.txt iconv -f SHIFT-JIS | dos2unix 1> gulliver_ryokoki_iconv.txt 
$ md5sum gulliver_ryokoki*
027a5821339608be2732d99d230ecfd0  gulliver_ryokoki.txt
33dcc1a4af39fa292ff422e875abf2e6  gulliver_ryokoki_hanamegane.txt
33dcc1a4af39fa292ff422e875abf2e6  gulliver_ryokoki_iconv.txt
33dcc1a4af39fa292ff422e875abf2e6  gulliver_ryokoki_pluma.txt
33dcc1a4af39fa292ff422e875abf2e6  gulliver_ryokoki_sakura.txt

「pluma」「サクラエディタ」で変換したファイルも添えました。okっすね。

おわり。きりがない。

続きを読む

初歩のシェルスクリプトで遊ぶ[シフトJISをutf8に変換-3,メガネハナーンを6226個に切り刻む]

調べものには使えません。
Ubuntu18.04,Virtualbox6.1.2,dash,bash

端末の平仮名をバラす

$ echo -n あ | od -An -tx1
 e3 81 82

「あ」をechoし、odに読ませると、「e3 81 82」と出ます。

$ echo -n あ 1>あ.txt
$ 0< あ.txt od -tx1
0000000 e3 81 82
0000003

「あ」をファイルにリダイレクトして、ファイルをodで読んでも、同じく「e3 81 82」。普通にエディタでも「あ」と読める、正しいテキストファイルが作れる。

$ cat あ.txt | head --bytes=1 > e3.file
$ 0< e3.file od -tx1
0000000 e3
0000001

「あ.txt」の1バイト目だけheadコマンドで切り取り、ファイルを作ると、「e3」だけになった。

$ 0< あ.txt  head --bytes=2 | tail --bytes=1 > 81.file
$ 0< あ.txt  head --bytes=3 | tail --bytes=1 > 82.file

同様に2バイト目、3バイト目をファイルにして、

$ cat e3.file 81.file 82.file 
あ 

「e3 81 82」の順にcatすると、「あ」と表示された。(実際に端末で実行すると改行なしで表示される)
catコマンドで「あ」と表示するには、「e3 81 82」と書かれた3バイトのファイルでなくてもよい。
「e3」と「81」と「82」の3ファイルでも構わない。

次に、同じように「や」でファイルを作る。「e3 82 84」だから、重複しない「84」を。

$ echo -n や  > や.txt
$ echo -n や | head --bytes=3 | tail --bytes=1 > 84.file
$ ls
81.file  82.file  84.file  e3.file  あ.txt  や.txt

元は「あ」と「や」だったファイルを、違う組み合わせでcatする、と?

$ cat e3.file 81.file 84.file 
い
$ cat e3.file 82.file 81.file 
め
$ cat e3.file 82.file 82.file 
も
$ cat e3.file 81.file 81.file 
ぁ
$ cat e3.file 81.file 82.file e3.file 82.file 84.file e3.file 81.file 84.file >あやい.txt
$ cat あやい.txt 
あやい
$ cat あやい.txt | od -tx1
0000000 e3 81 82 e3 82 84 e3 81 84
0000011

元の文字とは違う文字を、作ることができる。もちろんファイルにリダイレクトすることもできる。同じバイトを複数使っても構わない。

ここまでで、ごく小さなテキストファイルなら、catコマンドは1バイト単位で作れる、と分かった。
私はこんな使い方が想定されてるかなんて知りません。膨大な数はダメだとか、特定の文字しか作れないとか、環境依存とか、私には分かりませんが。


しかし、この前に7000個のファイルをcatコマンドで繋げ続けて、『ガリバー旅行記』を作ってみても、テキストエディタで作った正しいファイルとmd5が一致する、ということまでは分かってたわけです。

catコマンドは、人間が読むテキストファイルを連結したり、何ギガバイトもある大きなファイルを結合する、というもんだと思ってたのだけど。1バイト単位でも、やらせればできる、ってことは分かった。
catコマンドが悲鳴あげてるかもしれんけど。

256個のファイルがあれば、どんなファイルでも作れる?

「1バイトのファイル」は、多くても256種類あればいい。00〜FFまでなのだから。
もちろん全部を使える保証なんて無い。「00」だけ使えないとか、ありそうだ。しかしテキストファイルなら不要なバイトもあるだろう。7800個の辞書ファイルは、数を減らせるはず。

もし256種類使えたら?
テキストファイルだけでなく、「任意のファイルを作れるんじゃないの?」と考えたくなります。

1バイトのファイルをどうやって作るか

もちろん手段はいろいろ有るに決まっているのだけれど、私は他の言語も含めて知りません。xxdコマンドも知らなかった。echoやprintfでバイナリを作るのも、まだ調べてもいない。
Windowsバイナリエディタか何かを使うことも検討したけど、自分ができる範囲で、シェルスクリプトで考えたかった。

このとき思いついたのは、「小さなファイルをcatで組み合わせて大きなファイルを作る」のだから、逆に「大きなファイルを分割して小さくすれば、1バイトになるんじゃないの?」というもの。
模範解答をネットで探すより、手段があるなら作ったほうが早い。

メガネハナーンを6226個に切り刻む

cp932のテキストファイルをodコマンドで調べると、222種類と、だいぶ足りません。1バイトファイルの材料にはなりませんが、逆に、256種類なくてもテキストファイルなら作れる可能性はある、とわかった。

10年前の、メガネハナーンの落書きがありました。6226バイトのPNG画像です。

↑(注:この画像、アップロードしたら容量増えました。万一試すなら、お手元の手ごろな画像ファイルつかってください。)

cat hanamegane.png | od -An -v -tx1 | tr " " "\n" | sort | uniq -c |wc

odコマンドで調べると、256種類揃っていた。メガネハナーンを材料にします。

0< splitFile.temp split --bytes=1 

要点はココ。splitコマンドは、1バイトの指定でも受け付けてくれた。
作ったスクリプトは以下。

byteCellGenerator_02.sh

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'

■1バイトファイル作成スクリプト

メガネハナーンを千切りにして、1バイトのファイルを256種類生成する。


byteCellGenerator_02_01(){ # 作業場所の確認、実行の確認
byteCellGenerator_02_02(){ # ファイルを1バイト1ファイルに切り刻む
byteCellGenerator_02_03(){ # 1バイトファイルの中身を調べて名前変更する,重複を削除する

#--------------------------------------------------------------comment
# 設定
byteFileOutDir="./byteCellTemp/"  # ファイルを置くディレクトリを指定する
sengiriFile="./hanamegane.png"	# 切り刻み元のファイルを指定。せいぜい7000バイト程度に!



byteCellGenerator_02_01(){ # 作業場所の確認、実行の確認

# 作成するファイルの置き場所
mkdir "${byteFileOutDir}" 2>/dev/null
if mkdir "${byteFileOutDir}check/" ;then		# 試しに作成先に、ディレクトリを作成してみる
rmdir "${byteFileOutDir}check/"
else											# 作れなかったら終了
echo 作成先ディレクトリを確認 ;exit 1
fi

# 切り刻むファイル
sengiriFileSize=`cat "${sengiriFile}" | wc -c`
echo "${sengiriFileSize}"byte
if test 0${sengiriFileSize} -lt 6500 ;then		#最大ファイルサイズの制限
:
else
echo '終了する'
exit
fi

# 実行確認
echo "${byteFileOutDir}:作成先ディレクトリ"
echo "${sengiriFileSize}:生成予定ファイル数"
echo '[y]実行 [*]終了'
read action
case $action in
( y )
true
;;
( * )
echo '終了する' ;exit 0
;;
esac
}


byteCellGenerator_02_02(){ # ファイルを1バイト1ファイルに切り刻む

cp "${sengiriFile}" "${byteFileOutDir}"/splitFile.temp
(
	cd "${byteFileOutDir}"
	# 「--bytes=1」は、まず「--bytes=1000」以上でテストすること
	0< splitFile.temp split --bytes=1 --numeric-suffixes=0 --suffix-length=6 --additional-suffix=".chip" --verbose
)
rm "${byteFileOutDir}"/splitFile.temp
if test ${?} -ne 0 ;then
exit
else true
fi
}


# 1バイトファイルの中身を調べて名前変更する,
# 同一内容のファイルを上書きしてゆき、256種類以下に減らす
byteCellGenerator_02_03(){
(
cd ${byteFileOutDir} # mvでリネームと上書きをするためにcdする
sengiriChipS="`echo *.chip`"

chipCount=`echo ${sengiriChipS} | wc -w `
echo ${chipCount}:ファイル数

# 実行確認
echo 'ファイルを検査、リネーム、重複削除'
echo '[y]実行 [*]終了'
read action
case $action in
( y )
true
;;
( * )
echo '終了する' ;exit 0
;;
esac

# 主処理
for chip in ${sengiriChipS} ;do
chipHex=`od -An -tx1 -v "${chip}"`
mv -v "${chip}" ${chipHex}
done
ls
echo `ls | wc -w`" 種類"
)
}


byteCellGenerator_02_01
byteCellGenerator_02_02
byteCellGenerator_02_03

exit 0
実行結果
renamed 'x006219.chip' -> '45'
renamed 'x006220.chip' -> '4e'
renamed 'x006221.chip' -> '44'
renamed 'x006222.chip' -> 'ae'
renamed 'x006223.chip' -> '42'
renamed 'x006224.chip' -> '60'
renamed 'x006225.chip' -> '82'
00  09	12  1b	24  2d	36  3f	48  51	5a  63	6c  75	7e  87	90  99	a2  ab	b4  bd	c6  cf	d8  e1	ea  f3	fc
01  0a	13  1c	25  2e	37  40	49  52	5b  64	6d  76	7f  88	91  9a	a3  ac	b5  be	c7  d0	d9  e2	eb  f4	fd
02  0b	14  1d	26  2f	38  41	4a  53	5c  65	6e  77	80  89	92  9b	a4  ad	b6  bf	c8  d1	da  e3	ec  f5	fe
03  0c	15  1e	27  30	39  42	4b  54	5d  66	6f  78	81  8a	93  9c	a5  ae	b7  c0	c9  d2	db  e4	ed  f6	ff
04  0d	16  1f	28  31	3a  43	4c  55	5e  67	70  79	82  8b	94  9d	a6  af	b8  c1	ca  d3	dc  e5	ee  f7
05  0e	17  20	29  32	3b  44	4d  56	5f  68	71  7a	83  8c	95  9e	a7  b0	b9  c2	cb  d4	dd  e6	ef  f8
06  0f	18  21	2a  33	3c  45	4e  57	60  69	72  7b	84  8d	96  9f	a8  b1	ba  c3	cc  d5	de  e7	f0  f9
07  10	19  22	2b  34	3d  46	4f  58	61  6a	73  7c	85  8e	97  a0	a9  b2	bb  c4	cd  d6	df  e8	f1  fa
08  11	1a  23	2c  35	3e  47	50  59	62  6b	74  7d	86  8f	98  a1	aa  b3	bc  c5	ce  d7	e0  e9	f2  fb
256 種類

いけました。

組み立てる

入力データに従って、ファイルを組み立てます。
入力の規格は、以下のodコマンドの出力と同じ、とします。

$ echo あいうえおかきくけこ | od -An -tx1 -v
 e3 81 82 e3 81 84 e3 81 86 e3 81 88 e3 81 8a e3
 81 8b e3 81 8d e3 81 8f e3 81 91 e3 81 93 0a

組み立てるスクリプトは、最小限ならこれだけで済みます。
・while-read版

# 1バイトの組み立て部品ファイル置き場
byteCellDir="./byteCell0x/"
cd "${byteCellDir}"
while read byteLine ;do
eval cat ${byteLine}
done

1バイトファイルの入ったディレクトリに移動して、「e3 81 82 e3 81 84 e3 81 86 e3 81 88 e3 81 8a e3」~の文字列を、1行ずつcatするだけ。
1バイトファイルのファイル名を、中身と同じ16進数にしています。
こうすると、入力文字列を加工もせずに、catコマンドにまとめて渡すだけで、数字そのままのバイナリをcatし続けることができる。とても単純。

(evalはzshのために入れてます。bashやdashなら、要りません。)

・xargs版

# 1バイトの組み立て部品ファイル置き場
byteCellDir="./byteCell0x/"
cd "${byteCellDir}"
xargs cat

実際に組むときは、もうちょい追加すると性能が出ます。

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'

■ 1バイトのファイルを組み合わせて、任意のファイルを作成する〜「while read」版

▼ 手順
1)「00〜ff」256種類の1バイトファイルを用意する。
2)これら1バイトファイルから、catコマンドで結合ファイルを作成する。
3)入力データは、16進数を並べたテキストデータとする。


▼ 入力16進数文字列を、そのままcatコマンドの引数に使う
1バイトファイル名を、中身と同名の16進数のみにする。拡張子などは付けない。
入力データを、そのまま引数としてcatコマンドに渡す。
1バイトずつcatを実行するのではなく、1行分、下記では16バイトずつ実行する。

xargsでも同じ処理を書けるはずだが、それはそれ。

▼ odコマンドの出力に限定する
od --endian=big --address-radix=n --format x1 --output-duplicates
 e8 b5 a4 e5 b7 bb e7 b4 99 e9 9d 92 e5 b7 bb e7
 b4 99 e9 bb 84 e5 b7 bb e7 b4 99 0a

・16進数、1バイトずつ、空白区切り。
・改行が必要。16バイトずつ程度だが、増減は許容すべき。

▼速度
$ time cat gulliver-utf8Code02.txt | dash ./binCreator_02.sh >/dev/null
real	0m5.074s
user	0m2.030s
sys	0m2.915s

#--------------------------------------------------------------comment

# 1バイトの組み立て部品ファイル置き場
byteCellDir="./byteCell0x/"

binaryCreator_02(){
: << '#--------------------------------------------------------------comment'
「eval cat」のevalは、zshへの対応。
「tr,sed」の行は、入力の対応の拡大と、高速化。削除しても動作する。
1行を長くすると、高速になる。もちろん限度はある。

行の折り返しはfoldかfmtで行う。
foldは「-s」が必要。終端に改行がつかない。改行のない最終行が失われることを
防ぐため、whileループと直後の「eval cat」をサブシェルの括弧で括る。
#--------------------------------------------------------------comment

cd "${byteCellDir}"

tr -d " " | tr -d "\n" | sed -e 's/../ &/g;y/ABCDEF/abcdef/' |  fold -s -w 1200 |
(
while read byteLine ;do
eval cat ${byteLine}
done
eval cat ${byteLine}
)
}



: << '#------------------------------test'
echo -n "  e8 b5 a4 e5 b7 bb e7 b4 99 e9 9d 92 e5 b7 bb e7
 b4 99 e9 bb 84 e5 b7 bb e7 b4 99 0a " |
#------------------------------test

binaryCreator_02



exit 0

追加で試験しました。WindowsFirefoxの、setup.exe。

$ time 0< ./FirefoxSetup72.0.2.exe od -An -v -tx1 | dash ./binCreator_02.sh >FirefoxSetup72.0.2.exe_copy
real	15m8.692s
user	4m25.774s
sys	10m24.367s
$ md5sum FirefoxSetup72.0.2.exe*
c583a5b233a03141a5308afa8019f76b  FirefoxSetup72.0.2.exe
c583a5b233a03141a5308afa8019f76b  FirefoxSetup72.0.2.exe_copy

いけますね。バイナリファイルでも。

#!/bin/sh
#set -x
: << '#--------------------------------------------------------------comment'

■1バイトのファイルを組み合わせて、任意のファイルを作成する〜「xargs」版
xargsに書き換えて、while-readループを排除する。引数の数の調整なども任せる。
xargsでも、改行のない最終行は、処理できるようだ。

・xargs cat
$ time cat gulliver-utf8Code02.txt | ./binaryCreator_03.sh >/dev/null
real	0m3.001s
user	0m0.931s
sys	0m1.952s

・tr -d "\n" | xargs -d " " -I @@ cat @@
$ time cat gulliver-utf8Code02.txt | ./binaryCreator_03.sh >/dev/null
real	5m59.764s
user	4m18.513s
sys	0m55.739s

#--------------------------------------------------------------comment

# 1バイトの組み立て部品ファイル置き場
byteCellDir="./byteCell0x/"

binaryCreator_03_01(){
(
cd "${byteCellDir}"
xargs cat
)
}

: << '#------------------------------test'
echo -n "  e8 b5 a4 e5 b7 bb e7 b4 99 e9 9d 92 e5 b7 bb e7
 b4 99 e9 bb 84 e5 b7 bb e7 b4 99 0a " |
#------------------------------test

binaryCreator_03_01

exit 0

任意のファイルを作れるのなら、テキストファイルだって作れる

16進数の文字列から、ファイルを作れるようになった。
16進数でなくても、10進数でもいい。ファイル名を変えるだけでいいから。


これはこれで纏めるとして、元の目的に戻ります。cp932のテキストファイルをodコマンドで読み、utf8に変換するには、どうしたらいいか。
結局は先のエントリに載せた、直接に文字をpritfで出力するのが比較的マシだったのだけど、utf8の16進数からテキストファイルに変換するのもやりました。
utf8の16進数にしておけば、別の文字コードにも変えられるだろうし、これはこれでアリだろう。


1バイトファイル方式、気に入ってはいるんすよ。ローテクで。
是非とも、メガネハナーンの切れ端を濃縮したファイルを使いたい。……ああ、これがホメオパシーというものか。なるほど。


つづく。

続きを読む

初歩のシェルスクリプトで遊ぶ[シフトJISをutf8に変換-2]

調べものには使えません。

なりゆき

初心者知識と行き当たりばったりで、軽く遊ぼうと思った。フォントを作るのに文字コード見てたのに、規格やらは何も知らんので、これを機会に少し知っておくのもいいだろうと。

↓最初に組んだのの出力がこれで、改行を無視してます。

0030 0031 0032 0033 
0009 0009 0074 0061 0062 
0020 0020 0020 0020 0020 0020 0020 0020 0020 0020 0073 0070 
9046 82cd 93f5 82d6 82c7 0020 8e55 82e8 82ca 82e9 82f0 
89e4 0020 82aa 0020 90a2 0020 924e 0020 82bc 0020 8fed 0020 82c8 0020 82e7 0020 82de 
974c 88d7 82cc 899c 8e52 0020 0020 8da1 93fa 897a 82a6 82c4 
90f3 82ab 96b2 8ca9 82b6 8140 8140 908c 82d0 82e0 82b9 82b8 

この数字を、端末で読めるutf8の文字と入れ替えると、文章は読めた。
てっきり文字が読めるところまで行けないかと思ってたので、すぐ読めてびっくりした。いや、TTEdit文字コード表を見ただけなもんで……。
文字への変換は、とりあえずはgrepで済ませてました。
テキストファイル、7800行のやつを作って、一行ずつ文字コードと文字をタブ区切りにして、grep

82988299	y
829a	z
829f	ぁ
82a0	あ

図書カード:ガリバー旅行記
テストに使ってたのは、青空文庫ガリバー旅行記です。
ガリバー旅行記一冊分で、4分近くかかりました。けど、とにかくできた。

面白いうちは続けよう

この後、改行「0a」も含めて数字の列で出力することにして。じゃあ、自分にどこまでできるか。
この時点でxxdコマンドのこととか、知りません。utf8の中身もわかりません。数字を文字と入れ替えるしかないかな、と思ってた。

文字コードを文字に変換する方法が決まらない。結局比較的マシだったのは、やっぱり丸暗記。

SJIS8298=''
SJIS8299=''
SJIS829a=''
SJIS829f=''
SJIS82a0=''
SJIS82a1=''

ガリバー、2秒で終わった。
しかしこれ、使う文字も使わない文字も、問答無用全部って、嫌だよこんなの。
一文字ずつディスクを読むよりは、機械に優しい気もするけど、でもねぇ。

7884ファイル

#!/bin/dash

: << '#--------------------------------------------------------------comment'
shiftJISテキストファイルを数値に変換したデータを受け取って、
辞書テキストファイルから文字を拾って、テキストファイルを復元する

--辞書形式:細胞辞書形式
$ time cat gulliver_ryokoki_0d0aCode.txt |./sjisCodeToChar16.sh >/dev/null
real	0m7.665s
user	0m5.994s
sys	0m1.503s
#--------------------------------------------------------------comment

dict="./dic/nukamisoCP932Dic_06_cell/"
#ls ${dict}*  && exit

sjisCodeToChar16(){
(
cd "${dict}"
while read line ;do
  cat ${line}
done ;
)
}

: << '#--------------------------------------------------------------test'
echo "0030 0031 0032 0033 0d0a 0009 0009 0074 0061 0062 0d0a 0020 0020 0020 0020 0020 
0020 0020 0020 0020 0020 0073 0070 0d0a 9046 82cd 93f5 82d6 82c7 0020 8e55 82e8 
82ca 82e9 82f0 0d0a 89e4 0020 82aa 0020 90a2 0020 924e 0020 82bc 0020 8fed 0020 
82c8 0020 82e7 0020 82de 0d0a 974c 88d7 82cc 899c 8e52 0020 0020 8da1 93fa 897a 
82a6 82c4 0d0a 90f3 82ab 96b2 8ca9 82b6 8140 8140 908c 82d0 82e0 82b9 82b8 " |
#--------------------------------------------------------------test
sjisCodeToChar16

exit 0


↑入力は、16進数の数字の列が、ひとつ1文字。これを一行ずつ読み、catにそのまま渡す。すると、数字に対応した文字の入った小さなファイルが、カレントディレクトリから読み込まれて、テキストファイルの切れ端になって、標準出力から飛んでゆく。1ファイル1文字のテキストファイルになってるわけです。
こんな頭の悪い方法でも、ガリバー旅行記が8秒で組めるし、結果として出来たファイルは、md5を取ってもちゃんとutf8のテキストファイルになりました。テキストエディタで変換したのと同じデータを作れる。


次は、この膨大な細かいファイルを、どうやって減らすか。
つづく。

続きを読む

初歩のシェルスクリプトで遊ぶ[シフトJISをutf8に変換-1]

調べものには使えません。
Ubuntu18.04 (Virtualbox) dash,bash

Windowsのテキストファイルを読む

$ cat "Windowsのcp932テキストファイル.txt" | od -tx1 | tail
0036160 fb c6 fb c7 fb c8 fb c9 fb ca fb cb fb cc fb cd
0036200 fb ce fb cf fb d0 fb d1 fb d2 fb d3 fb d4 fb d5
0036220 fb d6 fb d7 fb d8 fb d9 fb da fb db fb dc fb dd
0036240 fb de fb df fb e0 fb e1 fb e2 fb e3 fb e4 fb e5
0036260 fb e6 fb e7 fb e8 fb e9 fb ea fb eb fb ec fb ed
0036300 fb ee fb ef fb f0 fb f1 fb f2 fb f3 fb f4 fb f5
0036320 fb f6 fb f7 fb f8 fb f9 fb fa fb fb fb fc fc 40
0036340 fc 41 fc 42 fc 43 fc 44 fc 45 fc 46 fc 47 fc 48
0036360 fc 49 fc 4a fc 4b

シェルスクリプトの製作途中ではiconvを使ってもいいが、実際のテキストファイルの変換作業はodコマンドの数字からやってみます。
あくまで不真面目に。

いきなり作ったもの

図書カード:ガリバー旅行記
動作速度のテストに使ったのは、青空文庫の『ガリバー旅行記』です。
スクリプト本体と、スクリプトが読む「文字の辞書」のテキストファイル、を作るスクリプトで出来てます。
WindowsのシフトJISの文字リストを作るシェルスクリプト - HatenaDiary id:Narr
辞書ファイルを作るのに、このスクリプトも使ってます。

ちょっと長いんで、このエントリの分は、この1セットを載っけるだけにしときます。
いや、別のバージョンとか、けっこうたくさんあってですね。そっちのほうが面白いんすわ。バカっぽくて。

続きを読む

初歩のシェルスクリプトで遊ぶ[8進数を2進数に変換(不真面目)]

調べものには使えません。
Ubuntu18.04(Virtualbox6.1.2) dash,bash

8進数を2進数に変換

000 001 002 003 004 005 006 007 010 011 012 013 014 015 016 017 
020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 
040 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 
060 061 062 063 064 065 066 067 070 071 072 073 074 075 076 077 
100 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 
..............

↑こういう大量の、1バイトの8進数の列を、シェルスクリプトで2進数に変換するにはどうしたらいいんだろうか、という話。あくまで不真面目に。
たぶん模範解答的には、こんな感じだろう、とは思うけど。

tr "\n" " " | tr -s " " | sed 's/ / ;/g' | fold -s -w 1000 |
     xargs -I @@ echo 'obase=2;ibase=8;@@' | bc | fmt

私がやりたいのは、これじゃない。

続きを読む

初歩のシェルスクリプトで遊ぶ[head,tailコマンドでバイナリを切る]

調べものには使えません。
Ubuntu18.04,dash

odコマンドの偽物

headコマンド、tailコマンドで1バイト単位でファイルを読む、というか切り出せるか試すために、odコマンドの偽物を作りました。

$ echo あいうえお | ./odFake_01.sh 
 e3 81 82 e3 81 84 e3 81 86 e3 81 88 e3 81 8a 0a

↑こんな感じで。標準入力から、文字や画像データやらを流し込むと、16進数が出力されます。「xxd -r -p」でバイナリに変換すると、元のデータに戻る。
「00」~「ff」まで含んだ画像ファイルも、切り出すことはできるみたい。「00」を変数に入れると怒られますけどね。
標準入力から入れる仕様にしてますが、データが入ってきたら、すぐファイルに落としてます。

続きを読む