bar /で「foo」パターンと一致するファイル名を印刷するのではなく、「grep foo bar」が「grep:bar:is a directory」を印刷するのはなぜですか?

bar /で「foo」パターンと一致するファイル名を印刷するのではなく、「grep foo bar」が「grep:bar:is a directory」を印刷するのはなぜですか?

manこのオプションのページの説明grepは次のとおりです-d ACTION

入力ファイルがディレクトリの場合は、ACTIONそれを処理するために使用します。デフォルトでは、ACTIONisはread通常のファイルのようにディレクトリを読み込みます。 [...]

bar直感的に、これはディレクトリが(pingのために)私が入力したときに表示されるものとgrepほぼ同じ内容を含むテキストファイルと同じように扱われることを意味すると予想されます。つまり、およそ(変更内容によって異なる)一種の上部および下部に説明情報および/またはメタデータを表示する。vimvim foo

"============================================================================
" Netrw Directory Listing                                        (netrw v156)
"   /home/chris-henry/bar
"   Sorted by      name
"   Sort sequence: [\/]$,\<core\%(\.\d\+\)\=\>,\.h$,\.c$,\.cpp$,\~\=\*$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by  x:special
" ==============================================================================
../
./
foobar/
baz/
qux

この場合、grep -H foo bar出力が生成されます。

bar: foobar/

代わりにメッセージを提供してくださいgrep: bar: Is a directory。なぜこれですか?直感的な結果を得る(かなり単純な)方法はありますか(この単純な検索だけでなく、テキストファイル、バイナリファイル、およびディレクトリの一部または全部と一致する場所などのgrep foo *検索も可能です)。*

到着予定時刻(2021-07-22):許可された回答で提案され、コメントで確認されたように、それ自体は実際に私が予想したものと正確に一致します。通常のファイルと同様に、ファイル記述子を使用して()grep foo barへのシステムコールを呼び出します。readこの時点で内容を入力するのではなく、エラーコードが返され、適切な診断メッセージが印刷された後、次のファイルでプロセスが続行されます。これはエラーコード(時にはそうではありません)を返し、通常のファイルになるのと同じです。 。ssize_t read(int fd, void *buf, size_t count)barbarread*bufbarEISDIRgrepreadEINTREINVALbar

私の期待と現実の違いは、Linuxバージョンの動作から来ています(コメントによると、他のほとんどの最新バージョン)read。つまり、fdディレクトリが参照されると自動的に返されますEISDIR

到着予定時刻2(2021-07-23):この質問に対する主な動機は、説明された直感的な動作を得る必要がある緊急の必要性ではありません(私はこれが潜在的な二次的な利点として興味がありますが)。動機は、grep出力に基づいて(GNU)がマニュアルページの主張と矛盾するように見えるように動作する理由を理解することです。

答えはgrep、実際にはマニュアルページに記載されているように実行しているということです。ただし、システムコールの(一般的な)動作が変更されたread場合結果ほとんどの最新システムでは、grep(最新の実装の動作に慣れていない状態で)マニュアルページを読むだけでread推論できるものとはかなり異なります。

全体的に私はこのことをしないほうがよいでしょうがread、この行動が次のような関係があるかどうか疑わしいです。それマンページ。現在の状況を考慮すると、マニュアルページに1〜2行を追加したかったのですが、grepそうではありません。間違った実際、それは誤解を招くだけです。

ベストアンサー1

ディレクトリにはテキスト形式の本質的な表現はありません。多くのUnixバリアントでは、プログラムが通常のファイルのようにディレクトリからデータを読み取ることができますが、コンテンツ形式はファイルシステムによって異なるため、これはほとんど役に立ちません。 Linuxを含むいくつかの最新のUnixバリアントプログラムがディレクトリを通常のファイルであるかのように読み取ることを完全に防ぎます。

たとえば、次はFreeBSDで何が起こるかです(以前のバージョンではまだ許可されています。FreeBSD 13以降はデフォルトで無効になっています)。次のディレクトリは次のとおりですbar

$ grep -H foo bar
Binary file bar matches
$ grep -H --text foo bar
bar:�"!
       .�
..�"!foobar�"!
              baz�"!qux

はい、ディレクトリ表現に存在するかどうかはわかりますが、fooファイル名の一部であるかどうかはわかりません。たとえば(まだFreeBSDシステムにあります):

$ rmdir bar/foobar
$ grep -H --text foo bar 
bar:�"!
..�"!foobar�"!
              baz�"!foo

ディレクトリを削除すると、ファイルシステムからディレクトリが削除されますが、ディレクトリをエンコードするディスク構造から削除されたエントリの名前は消去されません。

Vimにディレクトリを開くように要求すると、Vimはディレクトリをナビゲートし(たとえば、readdir一般的な機能を使用するのではなく特殊なシステム機能を使用してread)、結果を見やすく表示します。

Grepは同様のものを実装できますが、grepのサイズに比べて多くの作業が必要であり、ファイルの内容を検索するgrepの重要な目的から逸脱し、実装が満足のいく妥協でなければなりません。多くの人。ディレクトリのテキスト表現にはファイル名または一部のメタデータのみが含まれていますか(grep "Jul 20" bar7月20日に変更されたファイルが見つからないのですか)。項目を区切る方法(ファイル名に改行を含めることができるため、改行で区切られている場合は表現があいまいです。ヌルバイトで区切られている場合、出力は役に立ちますgrep --null-data)。

シェルワイルドカードfindlocate

おすすめ記事