標準入力があるかどうか判断して実行するスクリプト
標準入力がある場合はその内容を、そうでない場合は適当に与えられた ファイルの内容を表示するスクリプトを考えます。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
こんな感じ。testコマンドの-t
はman testによると
-t file_descriptor
True if the file whose file descriptor number is
file_descriptor is open and is associated with a terminal.
と言うことで、上の場合、標準入力0を指定して、これが 現在のターミナルと関連付けられてたりしたらTrueになります。
パイプを使って標準入力を渡したりすると、これが切れるのFalseになります。
同じことが-p
を使うと
-p file True if file is a named pipe (FIFO).
とのことなので、この場合は/dev/stdin
を指定してやって
これが名前付きパイプならTrue。
つまり、パイプで標準入力が来るとこの場合はTrueになります。
ので、
$ echo "from file" > $file
$ ./a.sh
from file
とした場合はfile
の内容が表示され、
一方
$ echo "from file" > $file
$ echo "from pipe" | ./a.sh
from pipe
の様にパイプ後に使用すると渡された値が表示されます。
上のスクリプトで入力を受け取った後にキー入力をしたい
read
でキー入力を受け取って何か操作するようなことを、
上のスクリプトの中で行いたいとします。
単純に何かキーを押したら終了するようなものを入れてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
これで、そのまま起動すると
$ echo "from file" > $file
$ ./a.sh
from file
push any key to exit:
で止まって、キーを押せばexit
を表示されて終了します。
終了後のステータスはもちろん0(正常)です。
(上のread
の無いスクリプトも両方0)
一方、パイプを使って入力を与えると
$ echo "from file" > $file
$ echo "from pipe" | ./a.sh
from pipe
push any key to exit:
$
と、キーを押す前に勝手に終わってしまい、更に終了ステータスを見ると1で正しく終わってません。
最後のread
の所で、入力はパイプからになってるのに、
既に入力は全て上のwhile文で使われてしまってるので
そこで失敗しています。
解決法
read
の部分に現在の端末からの入力を与えてあげればいいので、
/dev/tty
から入力される様にするだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
これでパイプで渡しても
$ echo "from pipe" | ./a.sh
from pipe
push any key to exit:
と、待ってくれる様になってキーを押したら正常終了してくれます。
追記
カテゴリーをcoputer
にしてしまってURLにcoputer
が入ってしまいました。。。
変えるといろいろ面倒だからカテゴリだけ書き換えてURLはそのままにしときます。。。
追記ここまで