初歩のシェルスクリプトで遊ぶ[ファイルのリネームツール、のようなもの?_(1)]
名前は「burdock」
シェルスクリプトでファイルのリネームツールを作って……作れたのかなぁ。リネームできてるっちゃあできてますが、画像の形式変換だとかもできちゃうんすけど……。
使用例
1.写真ファイルからexif情報を取り出してリネーム_端末用インターフェースから
(途中でテキストファイルを編集する必要あり)
- UIのプラグインスクリプトでImageMagickを実行、EXIF情報をテキストファイルに書き出し、
- 別の任意のツールでテキストファイルを編集してから、
2.ファイルに乱数のサフックスをつけてリネーム_コマンドラインから
- シェル変数モードに変更し、
- コマンド実行モードを1ファイル1実行モードに切り替え、
- サフックスに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' ;
初歩のシェルスクリプトで遊ぶ[シフト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
追加で試験しました。WindowsのFirefoxの、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。
8298 x 8299 y 829a z 829f ぁ 82a0 あ
図書カード:ガリバー旅行記
テストに使ってたのは、青空文庫のガリバー旅行記です。
ガリバー旅行記一冊分で、4分近くかかりました。けど、とにかくできた。
面白いうちは続けよう
この後、改行「0a」も含めて数字の列で出力することにして。じゃあ、自分にどこまでできるか。
この時点でxxdコマンドのこととか、知りません。utf8の中身もわかりません。数字を文字と入れ替えるしかないかな、と思ってた。
文字コードを文字に変換する方法が決まらない。結局比較的マシだったのは、やっぱり丸暗記。
SJIS8298='x' SJIS8299='y' SJIS829a='z' 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」を変数に入れると怒られますけどね。
標準入力から入れる仕様にしてますが、データが入ってきたら、すぐファイルに落としてます。