[unix] パイプ処理時のバッファリングではgrepやsedに出力のバッファリングオプションがオプションがあるのを見た。
他にも出力先によって、動作が変わるコマンドはある。
むしろ、縦に並べる方が本来で、端末の場合は見やすくしてくれていると考えた方がいいかもしれない。
out_test.c
Linux Programmer's Manual ISATTY(3)
Linux Programmer's Manual STAT(2)
例えば、出力先がパイプの場合でも、1行毎に出力したい場合は _IOLBF を指定する。
buffer_test.c
これをURL同様に実行すると、パイプを経由しても、1行毎に出力されることがわかる。
Linux Programmer's Manual SETBUF(3)
他にも出力先によって、動作が変わるコマンドはある。
lsの出力
例えば、lsも出力先が端末だと、ファイル名を適当に区切って並べてくれるけど、出力先がパイプだと、ファイル名を縦に並べる。むしろ、縦に並べる方が本来で、端末の場合は見やすくしてくれていると考えた方がいいかもしれない。
$ ls bar buzz foo $ ls | cat bar buzz foo $
標準出力の接続先を確認
こんな風に標準出力の接続先に応じて、プログラムの動作を変えたい時はisattyやfstatを使って、ストリームがどこに繋がっているか調べればいい。out_test.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main(void) { struct stat st; if (isatty(fileno(stdout))) { printf("terminal.\n"); return 0; } fstat(fileno(stdout), &st); if (S_ISFIFO(st.st_mode)) { printf("pipe.\n"); return 0; } printf("file.\n"); return 0; }
$ ./out_test terminal. $ ./out_test | cat pipe. $ ./out_test >test.log; cat test.log file. $
Linux Programmer's Manual ISATTY(3)
Linux Programmer's Manual STAT(2)
バッファリングモードを変更
grepやsedのようにオプションとかで出力のバッファリングモードを変更したい場合はsetvbufで変更できる。例えば、出力先がパイプの場合でも、1行毎に出力したい場合は _IOLBF を指定する。
buffer_test.c
#include <stdio.h> int main(void) { char buf[4096]; setvbuf(stdout, NULL, _IOLBF, 0); while (fgets(buf, 4096, stdin)) { fputs(buf, stdout); } return 0; }
これをURL同様に実行すると、パイプを経由しても、1行毎に出力されることがわかる。
$ seq 10 | xargs -I% sh -c 'sleep 1; echo %' | ./buffer_test | cat 1 2 3 4 5 6 7 8 9 10 $
Linux Programmer's Manual SETBUF(3)
0 件のコメント:
コメントを投稿