環境
- PowerShell 5.1
- PowerShell 6.0
Format-Hexコマンドレット
odコマンドのようなファイル等の16進数ダンプ表示ができるFormat-HexがPowerShellバージョン5で追加された。ただし今のところ16進数専用でオプションはあまりなく、odコマンドのエイリアスではないようだ。
バイナリファイルをダンプ
ヘルプ例にあるようにファイルタイプ判別でファイル先頭のヘッダ部分を表示したい用途等で使える。
PS C:\temp> Format-Hex -Path ".\pngfile.dat"
パス: C:\temp\pngfile.dat
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 ?PNG........IHDR
00000010 00 00 01 8C 00 00 00 E6 08 02 00 00 00 49 43 25 ...?...a.....IC%
... (以下略)
他のプロセスでファイルを開いていると例外エラーになってしまう。
また、試した限り、右の文字列部分に日本語等のマルチバイト文字コードを正しく表示する方法はわかならかった。
ファイルサイズが大きい場合の注意
ファイルが小さければ、このまま問題なく使えるが、ファイルが大きい場合に出力をmoreに食わせるとメモリ消費や実行時間が増え、表示し始めるまでに時間がかかってしまう現象があった。
ページャを使わなければそのようなことはないが、出力が大量に出てしまう。ctrl-cで止められるが、使いにくい。
試した結果、moreを使うよりSelect-Objectのほうが表示し始めるまでの時間が速いことがわかった。
どうやらmoreは前段の処理結果をすべて一旦メモリに蓄えてから表示しはじめるようで、Select-Objectならばすぐにパイプライン処理が始まる点が違う模様。
moreを使う
PS C:\temp> Format-Hex .\bitmap100KB.dat | more
パス: C:\temp\bitmap100KB.dat
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 42 4D C6 90 01 00 00 00 00 00 36 00 00 00 28 00 BMA?......6...(.
00000010 00 00 91 02 00 00 34 00 00 00 01 00 18 00 00 00 ..?...4.........
... (以下略)
Select-Objectを使う
# 先頭256バイトを表示(16バイト単位のByteCollectionのため16で割る)
PS C:\temp> Format-Hex .\bitmap100KB.dat | Select-Object -First (256/16)
パス: C:\temp\bitmap100KB.dat
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 42 4D C6 90 01 00 00 00 00 00 36 00 00 00 28 00 BMÆ......6...(.
00000010 00 00 91 02 00 00 34 00 00 00 01 00 18 00 00 00 .....4.........
... (以下略)
# 8KBスキップして256バイトを表示
PS C:\temp> Format-Hex .\bitmap100MB.dat | Select-Object -Skip (8KB/16) -First (256/16)
Path: C:\temp\bitmap100MB.dat
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00002000 0A 2D 4E 0A 2D 4E 0A 2D 4E 0A 2D 4E 0A 2D 4F 0A .-N.-N.-N.-N.-O.
00002010 2D 4F 0A 2D 4F 0A 2C 4F 09 2C 4F 09 2C 4F 09 2C -O.-O.,O.,O.,O.,
... (以下略)
# アドレス0x1C00から256バイト表示
PS C:\temp> Format-Hex .\bitmap1MB.dat | Select-Object -Skip (0x1C00/16) -First (256/16)
パス: C:\temp\bitmap1MB.dat
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00001C00 4C 08 28 4C 07 28 4C 06 28 4D 06 28 4D 06 28 4C L.(L.(L.(M.(M.(L
00001C10 06 29 4D 07 2A 4E 08 2B 4E 09 2A 4E 08 29 4E 07 .)M.*N.+N.*N.)N.
... (以下略)
ただしSelect-Objectを使っても、skipがMB単位とか大きくなるほど、やはり時間がかかってしまいどうしようもなかった。基本的にファイル先頭付近を見るのに使うしかなさそう。Format-Hexにskipオプションができればいいのだが。
表示し始める時間の比較結果
PowerShell 5.1
ファイルサイズ | more(最初の表示まで) | select(先頭1KBを表示) |
---|---|---|
100KB | 5.1秒 | 0.16秒 |
1MB | 49.5秒 | 0.16秒 |
10MB | 202.1秒 | 0.14秒 |
100MB | 未計測 | 0.16秒 |
300MB | 未計測 | 0.13秒 |
PowerShell 6.0
ファイルサイズ | more(最初の表示まで) | select(先頭1KBを表示) |
---|---|---|
100KB | 0.3秒 | 0.050秒 |
1MB | 0.3秒 | 0.047秒 |
10MB | 0.9秒 | 0.054秒 |
100MB | 5.2秒 | 0.066秒 |
300MB | 22.4秒 | 0.068秒 |
5.1と6.0では実装が変わっているせいなのか違いが大きい模様。