意味不明なタイトルですみません。
今回は/dev/stdinについて教えてください。
/dev中のファイルは特殊ファイルなので深追いしない方がいいとは思うのですが詳しい方お願いします。
次のコマンドとその出力を見てください。
$ echo "a
> a
> a
> a
> a" | while read LINE
> do
> grep -l str $LINE
> done
a
a
a
a
a
$
これはgrepにファイルaを5回検索させる命令ですが
この5行のaの途中に/dev/stdinを挿入すると次のように/dev/stdin以降が出力されなくなってしまうのです!!
$ echo "a
> /dev/stdin
> a
> a
> a
> a" | while read LINE
> do
> grep -l str $LINE
> done
a
$
この/dev/stdinとはいったい何者なのですか!?
このコマンドでは、いったいどのような事態が起こっているのですか!?
No.1
- 回答日時:
>この/dev/stdinとはいったい何者なのですか!?
標準入力
ぐぐれば、すぐわかるはずですが。
mtfoggyさん、アドバイスありがとうございます。
/dev/stdinというファイルが何者かということについては、
すぐにとはいかないまでも、頑張ってぐぐれば自力で回答を導き出せる疑問でした。
またstdinという名前から自分でも恐らく標準入力を表すファイルなのだろうと予想していたのでした。
今回は質問文中の2個目の命令行のような見慣れない出力を発見したので、
これを皆さんに見てもらいたいと思い、ここへ質問に参ったというわけです。
その際ついでに/dev/stdinとは何かという容易な質問もしてしまったわけですが許してください~w
No.2ベストアンサー
- 回答日時:
>> a" | while read LINE
>> do
>> grep -l str $LINE
>> done
grepコマンドの前に
echo "grep -l str $LINE"
とかを入れてみると、grepがどういう実行イメージで何回実行されるか分かると思いますよ。
上記を実施してみれば分かりますが、2回目に
grep -l str /dev/stdin
が実行されるのは分かりますよね?
/dev/stdinが何で、上記が実行されるとどこから読み込みが行われ、その時どういう内容が読み込まれるのか理解出来れば、何故そうなるのか分かると思いますよ。
理解出来ないなら、一番の最初に書いたecho "grep -l str $LINE"
を追加して、さらに
>> grep -l str $LINE
を
cat $LINE
にでも変更して実行してみれば理解出来ると思いますよ。
この回答への補足
Leanさん、ご返信ありがとうございます。
助言いただいたとおりに操作してみました。
まず、grepコマンドの前にecho "grep -l str $LINE"を入れてみました。
$ echo "a
> /dev/stdin
> a
> a
> a
> a" | while read LINE
> do
> echo "grep -l str $LINE"
> grep -l str $LINE
> done
grep -l str a
a
grep -l str /dev/stdin
$
1回目のループではecho、grepともに予想通りの出力です。
2回目のechoも予想通りです。
2回目のgrepは何も出力しません。
これは/dev/stdinに文字列strがないことを物語っています。
そして処理は終了します。
whileは入力行がある限り繰り返すはずなのにここで終了してしまうということは、
実はすでに最終行まで入力が終了しているということ??
これだけでは、よく分からないので、
次にgrep -l str $LINEをcat $LINEに変更してみました。
$ echo "a
> /dev/stdin
> a
> a
> a
> a" | while read LINE
> do
> echo "grep -l str $LINE"
> cat $LINE
> done
grep -l str a
str
grep -l str /dev/stdin
a
a
a
a
$
1回目のループではecho、catともに予想通りの出力です。
2回目のechoも予想通りです。
2回目のcatの出力は"a
a
a
a"でしょうか
2回目のcatとはすなわち
cat /dev/stdin
であるため、
/dev/stdinの内容は"a
a
a
a"であるといえます。
そして3回目のループは実行されない。
それは2回目のループまでで、全ての入力行が終了してしまうからということでしょうか。
整理します。
/dev/stdinとは標準入力のこと。
そして、ここでいう標準入力は"a
/dev/stdin
a
a
a
a"です。
しかし/dev/stdinの内容はそれ以降に入力した"a
a
a
a"となっていました。
そして、入力したはずの"a
a
a
a"はかき消されていて、
かき消された内容は/dev/stdinの内容と一致する!?
うーん頭が混乱してきましたが、自分なりに打ち出した見解はこうです。
/dev/stdinは標準入力の内容を保持しているが、絶え間なく更新しているため、
catで中を覗こうとしても、そのタイミングにより、様々な結果が表示される。
また、標準入力は1個しかないので、たとえ仮想的に標準入力を表す/dev/stdinを覗いたとしても、その時点で入力が完了したと判断され、元の入力はかき消されてしまう。
うまく説明できないのですが、こんな感じでしょうか。
今回の例では1回目のループ時点では/dev/stdinの内容は"a
/dev/stdin
a
a
a
a"でしたが、このとき1行目のaの入力が完了したため/dev/stdinの内容が"a
a
a
a"となり、2行目の入力は/dev/stdinなので全ての入力が一気に渡されwhile自体が終了したということかな・・・。
こう考えれば、つじつまが合う気がするのですが、いかがでしょうか。
No.3
- 回答日時:
最後に書かれた理解でいいと思います。
まず、echoによって標準入力(/dev/stdin)に
a
/dev/stdin
a
a
a
a
が入ります。
次に「while read LINE」で1行分(「a」)標準入力(/dev/stdin)から読み込まれますので、標準入力(/dev/stdin)の内容は、
/dev/stdin
a
a
a
a
になります。
次の「while read LINE」でまた1行分(「/dev/stdin」)標準入力(/dev/stdin)から読み込まれますので、標準入力(/dev/stdin)の内容は、
a
a
a
a
になります。
2回目のgrepの実行は
grep -l str /dev/stdin
になり、標準入力(/dev/stdin)からEOF(ファイルの最後)になるまで読み込まれます。
つまり、標準入力(/dev/stdin)に残っていた内容の
a
a
a
a
が全て読み込まれ、標準入力(/dev/stdin)には何も残っていない状態になり、「while read LINE」では読み込むものがないのでwhileループが終了になります。
Leanさん、お返事ありがとうございます。
いただいたヒントと今までの経験と知識を総動員して解答を導き出せたのですごい嬉しいです!
特殊ファイルとは、その名のとおり、普通のファイルとは1癖も2癖も違って、扱いが難しいですね。
今回、どうやって、本件の現象を発見したかといいますと、
今、指定ディレクトリー中の全ファイルをgrep検索するという、結構使えそうなシェルスクリプトを作成中でして、
これを例のごとくルートディレクトリーでテストしたところ/dev/stdin以降の結果が意図したものと全然ちがっていたのです。
これで原因が分かりました。
findで取得したファイル名をパイプを通してgrepに渡しているのですが、
このファイル名に/dev/stdinが含まれていた場合、このスクリプトの結果はめちゃくちゃになることが分かりました。
今考えられる修正案は、findで取得したファイル名の一覧に/dev/stdinが含まれていたら、これを取り除いてからgrepへ渡すということぐらいですが、
これは、あんまりかっこよくないので、もう少しいい回避策を考えてみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- UNIX・Linux Linuxのbash環境下です。 1 2022/11/27 12:31
- UNIX・Linux VirtualBox ゲストOSにPC内蔵HDDのパーティションをマウントする方法は? 2 2023/05/06 22:52
- UNIX・Linux swapが機能しているかの確認について 2 2022/09/18 13:17
- UNIX・Linux 次の要件を満たすにはどのように修正したらよろしいでしょうか 1 2022/11/24 20:57
- UNIX・Linux Kali Linuxで起動できない - Minimal BASH Like Line Editing 1 2022/06/03 13:14
- Perl bashスクリプト 2 2023/02/10 21:01
- C言語・C++・C# (C言語・配列)date[i]の分散を計算する場合 2 2022/07/24 15:06
- UNIX・Linux ubuntuで デイスク/deb/loopというドライブが出るがこれは何? 4 2023/06/04 16:52
- その他(プログラミング・Web制作) I2C接続のLCDディスプレイを使う 2 2023/05/01 17:15
- UNIX・Linux マスターブートレコード方式のbiosを使ったシステムでインストールされたlinuxで/dev/sda 1 2023/05/13 21:23
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ddコマンドでイメージをコピー...
-
Solaris10のコマンドで、RAIDを...
-
HDのフォーマット
-
ルートのパーティションのUs...
-
RedHatLinuxマシンでHDを増設し...
-
パーティションと論理ボリューム
-
df コマンドで表示される Files...
-
diskutilコマンドによるパーテ...
-
cshでエラー出力を出さないよう...
-
DISK2台使用してsolaris10にて...
-
/dev/stdinはそれ以降の入力を...
-
NFS mount できず fsck もこける
-
iqoo neo 9と言うスマホがある...
-
Dirコマンドでフォルダ内ファイ...
-
TOPコマンドで表示するCPU使用...
-
UNIX コマンドにおける # や円...
-
SONYの音楽ソフト「x-アプリ」...
-
空きIPアドレスを探す方法
-
スクリプトのエラー「unexpecte...
-
エクセルの表にヘンな枠が・・・
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ddコマンドでイメージをコピー...
-
パーティションと論理ボリューム
-
cshでエラー出力を出さないよう...
-
ルートのパーティションのUs...
-
ディスクの全容量を知りたい
-
ディスク未使用領域容量の取得
-
デバイスファイルの考え方
-
df コマンドで表示される Files...
-
【Ubuntu】ext3ファイルシステ...
-
領域テーブル項目がディスクの...
-
KNOPPIXがHDDを認識しません
-
UbuntuとWinマスタUDF形式Blu-ray
-
小さい容量のHDDを大きなHDDに...
-
fdiskコマンドの表示の意味を教...
-
HP-UXにおけるDVDのmountについて
-
1セクタは何バイトかを表示す...
-
Solaris10のコマンドで、RAIDを...
-
起動時に"Can't read disk labe...
-
linux環境のinode数の変更方法...
-
Linux partedコマンドの使い方...
おすすめ情報