[unix]ファイル名しか受け付けないコマンドで標準入出力を使う方法

2016年10月15日土曜日

linux unix

Unixでフィルタ的な動きをするコマンドはたいてい標準入力と標準出力を扱えるけど、独自に作成されたツールでコマンド引数にファイル名しか受け付けないようなものもある。
そんなコマンドに対して前段後段の処理を実施する場合は一時的にファイルを作ることが考えられるだろう。
でも、パイプを使えば済むようなところでいちいちファイルを作るのはばかばかしいよね。
処理後に削除するとかも考えなくちゃいけないし。

そういう時は /dev/std* を参照すれば、標準入力、標準出力、標準エラー出力にアクセスできる。

/dev/stdin
/dev/stdout
/dev/stderr

例えばファイルをコピーするcpコマンドはコピー元のファイルとコピー先のファイルを指定する。
あまり実用的な例じゃないけど、標準入力の内容をファイルにコピーしてみよう。

$ cat foo | cp /dev/stdin bar

これでfooの内容がbarにコピーされる。
もちろん、stdoutに書き込めば、さらに後段に渡すこともできる。

$ cat foo | cp /dev/stdin /dev/stdout | tac

ただし、エラーメッセージを標準エラー出力ではなく、標準出力に出力するようなコマンドだと出力がごちゃごちゃになってしまうことがあるので注意しよう。

/dev/std* はシンボリックリンクになっているので、実際にどこにつながっているかはリンク先を見てみればわかる。
自プロセスの標準入出力がどこにつながっている確認してみよう。

# openSUSE Linux 13.1の場合
$ ls -l /dev/std*
lrwxrwxrwx 1 root root 4 Sep 25 15:17 /dev/stderr -> fd/2
lrwxrwxrwx 1 root root 4 Sep 25 15:17 /dev/stdin -> fd/0
lrwxrwxrwx 1 root root 4 Sep 25 15:17 /dev/stdout -> fd/1
$ ls -l /dev/fd
lrwxrwxrwx 1 root root 13 Sep 25 15:17 /dev/fd -> /proc/self/fd
$ ls -l /proc/self/fd
total 0
lrwx------ 1 bob users 64 Sep 25 16:00 0 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 25 16:00 1 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 25 16:00 2 -> /dev/pts/1
lr-x------ 1 bob users 64 Sep 25 16:00 3 -> /proc/2134/fd

この場合はターミナル(pts1)につながっていることがわかる。

リダイレクトやパイプを使用した時は標準入出力がつながっている先が以下のように変わるのがわかるね。

$ cat dev_test.sh
#!/bin/bash
exec 3>&1

ls -l /dev/fd/1
exec 1>dev.dat
ls -l /dev/fd/1
exec 1>&3
cat dev.dat
ls -l /dev/fd/

exec 3>&-
ls -l /dev/fd/ 

echo foo | ls -l /dev/fd/

$ ./dev_test.sh
lrwx------ 1 bob users 64 Sep 26 22:03 /dev/fd/1 -> /dev/pts/1
l-wx------ 1 bob users 64 Sep 26 22:03 /dev/fd/1 -> /home/bob/dev.dat
total 0
lrwx------ 1 bob users 64 Sep 26 22:03 0 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 1 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 2 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 3 -> /dev/pts/1
lr-x------ 1 bob users 64 Sep 26 22:03 4 -> /proc/2146/fd
total 0
lrwx------ 1 bob users 64 Sep 26 22:03 0 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 1 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 2 -> /dev/pts/1
lr-x------ 1 bob users 64 Sep 26 22:03 3 -> /proc/2147/fd
total 0
lr-x------ 1 bob users 64 Sep 26 22:03 0 -> pipe:[44062]
lrwx------ 1 bob users 64 Sep 26 22:03 1 -> /dev/pts/1
lrwx------ 1 bob users 64 Sep 26 22:03 2 -> /dev/pts/1
lr-x------ 1 bob users 64 Sep 26 22:03 3 -> /proc/2149/fd