grepがデフォルトでfindコマンドの端末出力から行を削除しないのはなぜですか? [コピー]

grepがデフォルトでfindコマンドの端末出力から行を削除しないのはなぜですか? [コピー]

私はしばしば次の簡単なコマンドのためにイライラしています。

find / | fgrep somestuff.ext

使用しないと、sudo権限が拒否された行が引き続き表示されます。これは公平ですが、grepがパイプから読み取ったときにこの出力が無視されないのはなぜですか?

この形式の出力がパイプに渡されるのではなく、ターミナルウィンドウに直接送信され(これが起こったと思われる)、その後grepによって無視されるのはなぜですか? catによって同じ行が生成されますが(許可拒否メッセージが保存されていると仮定)text)ファイルはパイプに正しく入り、私のgrepパターンでは無視されますか?

STDIN / STDOUTプロセスに私が理解していないものがあるようです。

答え1

許可拒否メッセージは、stdoutではなくfindstderrに送信されます。 stderr全体をビットバケットにリダイレクトできます。

find 2>/dev/null | fgrep somestuff.ext

また、特定のファイルを見つけるためにgrepは必要ありません。

find . -name somestuff.ext

それでも申請できます2>/dev/null

許可拒否メッセージのみを表示したくない場合は、次のものを使用できます。

2> >(grep -v 'Permission denied' >&2)

バッシュから。

答え2

nemocaの良い答えこの問題を解決しながら発見した動作の理由は、bashの基本的なパイプ動作です(そしてほとんどのシェルでも想像しています)。

パイプラインのセクションで述べたようにman bash

コマンドの標準出力はコマンド2の標準入力にパイプされます。この接続は、コマンドで指定されたリダイレクトの前に行われます(以下のリダイレクトを参照)。

これは、stderrリンクが基本的stderrにパイプを介して供給されず、デフォルトのstderrリンクであるttyに駆動されることを意味します。command1command2

Bashのマニュアルには次のように記載されています。

|&を使用すると、コマンドの標準エラーは、標準出力に加えてcommand2の標準入力にパイプされます。これは2>&1 |の略です。

したがって、あなたの場合、grepコマンドにパイプするには、デフォルトで送信される/dev/stderrfindコマンドエラーは、次の2つの形式のいずれかでなければなりません。

find / |& fgrep somestuff.ext
find / 2>&1 | fgrep somestuff.ext

質問のタイトルは、「パイプが標準エラーを無視する理由」かもしれません。

答えは、bashとLinuxがstdoutデフォルトでこれを異なる方法で処理し、stderrユーザーが2つの出力を異なる方法で記録/処理できるからです。
たとえば、stdoutコマンド1をstdinコマンド2にパイプし、stderr.を使用してコマンド1をログファイルに送信できます2>errorlog.txt

実際、次のようにリダイレクトを指定せずにコマンドを実行すると、

find /

それは等しい

find / 1>/dev/stdout 2>/dev/stderr

最終的な解決策は次のとおりです。

find / 1>/dev/tty1 2>/dev/tty1 #assuming that you are logged in tty1

単一の検証が可能ですls

ls -all /dev/st*
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdout -> /proc/self/fd/1

ls -all /proc/self/fd/2
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/2 -> /dev/tty1

ls -all /proc/self/fd/1
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/1 -> /dev/tty1

何らかの理由でstdoutコマンドを「結合」するには(パイプの場合)または(すべての種類の出力リダイレクトの場合)、使用目的を明示的に宣言する必要がstderrあります。bash|&2>&1

関連情報