サーバーの空き容量やログの大きさを調べたとき、返ってくるのが桁の多い数字だけ、という場面はよくあります。
3500000 と言われても、それが 3.5MB なのか 35MB なのか、頭の中で三桁ずつ区切る手間が挟まってしまう。
かといって du -h のように、コマンド側が人間向けの単位を用意してくれているとは限りません。
そんなときに効くのが、数値の単位変換だけを担当する numfmtという小さなコマンドでした。
GNU coreutils に同梱されていて、パイプの途中に一つ挟むだけで、桁の多い数字が読める形に変わります。
この記事の実行例は、GNU coreutils 8.32(Windows 上の MSYS2 / bash 5.2)で実際に動かして確認しました。
まずは単位を付けるだけの –to
numfmt のいちばん基本の使い方は、数値を渡して単位付きに変換する形です。
指定するのは–to オプションで、二進接頭辞なら iec、十進接頭辞なら si を選びます。
$ numfmt --to=iec 1234567
1.2M
$ numfmt --to=si 1234567
1.3M
$ numfmt --to=iec-i --suffix=B 1234567
1.2MiB
同じ 1234567 でも、iec では 1.2M、si では 1.3M と結果が変わりました。
iec は 1024 で割り、si は 1000 で割るという違いがそのまま出ています。
どちらの基準で丸めた数字なのかを、単位を付ける側で明示できるのが numfmt の強みですね。
iec-i を選べば MiB のような正式表記になり、あとから見た人が基数を誤解しない出力になります。
小数の桁数を増やしたいときは --format を添えるだけ。
$ numfmt --to=iec --format="%.2f" 1234567
1.18M
パイプの途中で「その列だけ」変換する
numfmt が本領を発揮するのは、単独で使うときよりも、他のコマンドの出力を受け取るときでした。
対象の列を指定する --field、見出し行を読み飛ばす --header、桁を揃える --padding の三つで、表の形を保ったまま変換できます。
$ du -sb * | numfmt --field=1 --to=iec --padding=8
3.4M big.bin
800 small.bin
du -sb はバイト単位の数値を返すので、その 1 列目だけを iec に置き換える形。
--padding=8 を付けると右詰めで幅が揃い、桁の違う行が並んでも視線が迷わなくなります。
範囲指定もできるので、df のように複数列が数値のコマンドとも相性が良好。
$ df -B1 . | numfmt --header=1 --field=2-4 --to=iec
Filesystem 1B-blocks Used Available Use% Mounted on
C: 931G 735G 197G 79% /c
--header=1 を付けたおかげで、1 行目の見出しはそのまま残りました。
–field=2-4のような範囲指定で、必要な列だけをまとめて処理できています。
実際に踏んだ落とし穴
便利な一方で、手元で試している最中に三つほど引っかかった点がありました。
一つ目は、ls -l の出力をそのまま流し込んだときの列ズレです。
$ ls -l | numfmt --header=1 --field=5 --to=iec
-rw-r--r-- 1 Ryosuke Sasaki 193K 3500000 Aug 22 14:06 big.bin
サイズは 3500000 のまま残り、関係のない数字が 193K に化けてしまいました。
原因は、所有者名に空白が含まれていたせいで、5 列目の位置が一つ後ろへずれたこと。
numfmt の列は空白区切りで数えるため、列の中身に空白が入る出力とは相性が悪いわけです。
ls -l のような表を扱うなら、du -sb や stat のように区切りが安定した出力へ寄せるほうが安全でしょう。
二つ目は、数値以外の行が混ざったときの挙動でした。
$ printf 'a 1234567\nb notanumber\n' | numfmt --field=2 --to=iec
a 1.2M
b numfmt: invalid number: 'notanumber'
# 終了ステータスは 2
途中でエラーになり、終了ステータス 2 でパイプ全体が失敗扱いになります。
ログのような雑多な行を流すなら、--invalid=ignore を付けて素通りさせる判断も要りますね。
三つ目は、三桁区切りを入れる --grouping がロケール依存だという点。
C ロケールでは何も起きず、ja_JP.UTF-8 を指定して初めて 1,234,567 の形になりました。
スクリプトの中で桁区切りを当てにするなら、ロケールまで込みで指定しないと結果が環境で変わるので注意したいところ。
逆向きの変換も同じコマンドで
numfmt は単位を付けるだけでなく、単位付きの文字列を数値へ戻す方向にも使えます。
使うのは–from オプションで、設定ファイルや手入力の値を計算に載せたいときに便利。
$ numfmt --from=iec 1.5G
1610612736
1.5G が 1610612736 バイトに開かれました。
しきい値を「1.5G」のように人が読める形で書いておき、比較の直前にバイトへ戻すという使い分けができます。
丸め方を選べる --round もあり、up なら切り上げ、down なら切り捨てという指定。
$ numfmt --to=iec --round=up 1500
1.5K
$ numfmt --to=iec --round=down 1500
1.4K
容量の見積もりのように、安全側へ倒したい場面では効いてきます。
最後に
numfmt は、数値の見せ方だけを引き受けるという割り切りが気持ちのいいコマンドでした。
du -h のような専用オプションを持たないコマンドの出力でも、パイプに一つ挟むだけで読める形に整います。
覚えることは --to と --from、そして列を指す --field の三つだけ。
一方で、空白を含む列やロケールの前提が絡むと、結果が静かにずれる場面もありました。
小さなコマンドほど、手元の環境で一度出力を確かめてから運用に載せたいですね。
ディスクの空きと使用量そのものを調べる df・du のほうは、別記事で基本から整理しています。
以上です。










コメントを残す