はじめに
dd
コマンドを実行すると以下のようなステータスが出力されます。一般的には正常終了したときにはこのような出力は行わないのが Unix の流儀ですが dd
コマンドは変わったオプションの書式(JCL の流儀を踏まえているらしい)で、それもあってか正常終了でもステータス出力が標準エラー出力に出力されます。この記事ではこの出力を消す方法をまとめました。
【英語の場合】
$ dd if=/dev/urandom of=./random.bin bs=1k count=1
1+0 レコード入力
1+0 レコード出力
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00074 s, 1.4 MB/s
【英語の場合】
$ dd if=/dev/urandom of=./random.bin obs=10 bs=1k count=1
1+0 records in
1+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00074 s, 1.4 MB/s
status=none を使う
一般的な方法は status=none
を使います。非表示になるのはステータス情報のみで、エラーメッセージは出力されます。
$ dd if=/dev/urandom of=./random.bin bs=1k count=1 status=none
参考ですが status=noxfer
を指定すると、一番最後の転送情報のみが非表示になります。
$ dd if=/dev/urandom of=./random.bin bs=1k count=1 status=noxfer
1+0 records in
1+0 records out
ただし status
オプションは 2012 年頃の GNU coreutils、2014 年の FreeBSD 9.3 以降、2015 年の OpenBSD 5.5 以降、OpenIndiana の少なくとも 2023-05 版で利用可能ですが、NetBSD 9.3、Solaris 11 で非対応で POSIX でも標準化されていないので注意してください。
POSIX で標準化された範囲で実装する
status=none
に対応した環境であれば、それを使うのが楽ですがそうでない環境でやるにはどのようにしたら良いでしょうか? 一番簡単なのが標準エラー出力を /dev/null
に捨てる方法です。
$ dd if=/dev/urandom of=./random.bin bs=1k count=1 2>/dev/null
この方法はたしかにステータス出力を消すことができますが、エラーメッセージまでも消してしまうのでよくありません。
$ dd if=/dev/no-such-file of=./random.bin bs=1k count=1 2>/dev/null
$ echo $?
1 ← エラーになっている
【本来ならこのようなエラーが出力される】
$ dd if=/dev/no-such-file of=./random.bin bs=1k count=1
dd: failed to open '/dev/no-such-file': No such file or directory
エラーになったときだけエラーメッセージを出力したいので、次のような回避策を実装しました。これをシェルスクリプトの冒頭に入れておくだけでステータス出力を消すことができます。
# dd シェル関数(ラッパー)で本来の dd コマンドを置き換える
dd() {
# 標準出力はファイルディスクリプタ3 経由で迂回して出力し
# エラーメッセージは標準出力経由で変数にキャプチャしている
(
# command でシェル関数をバイパスして元の dd コマンドを呼び出す
err=$(command dd "$@" 2>&1 >&3) && : # 「&& :」は set -e でも機能させるため
ex=$?
# エラーのときだけ標準エラー出力にエラーを出力する
[ "$ex" -eq 0 ] || echo "$err" >&2
exit "$ex"
) 3>&1
}
# ステータスは出力はされない
dd if=/dev/urandom of=./random.bin bs=1k count=1
# => なし
# エラーメッセージは出力される
dd if=/dev/no-such-file of=./random.bin bs=1k count=1
# => dd: failed to open '/dev/no-such-file': No such file or directory