1. ホーム
  2. bash

[解決済み] 検索」からすべての「permission denied」メッセージを除外するにはどうすればよいですか?

2022-03-21 18:24:56

質問

をすべて非表示にする必要があります。 パーミッション拒否 からのメッセージ。

find . > files_and_folders

このようなメッセージが発生した場合、私は実験中です。このメッセージが発生しないフォルダとファイルをすべて集める必要があります。

にパーミッションレベルを指示することは可能ですか? files_and_folders ファイルを作成できますか?

エラーを同時に非表示にするにはどうしたらいいですか?

解決方法は?

注意

  • この回答は、おそらくユースケースが保証するよりも深いものであり find 2>/dev/null 多くの場合、これで十分かもしれません。 . この本は、クロスプラットフォームの視点と、可能な限り堅牢な解決策を見出すための高度なシェル技術の議論として、たとえ防御されるケースがほとんど仮説的であったとしても、興味を引くことができるでしょう。

もし、あなたが シェルは bash または zsh があれば、そこに 堅牢でありながら、適度にシンプルなソリューション を使用します。 POSIX準拠の find 機能 一方 bash はPOSIXの一部ではありませんが、最近のほとんどのUnixプラットフォームに搭載されているため、このソリューションは広く移植可能です。

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

  • を表示するように設定されている場合 ローカライズ エラーメッセージの前に find の呼び出しは、以下のように LC_ALL=C ( LC_ALL=C find ... )を確保するために 英語 メッセージが報告されるように grep -v 'Permission denied' は意図したとおりに動作する。しかし、常に する と表示され、英語表記になる。

  • >(...) は、(めったに使われない) 出力 プロセス代替 という、出力のリダイレクトを可能にするもの(この場合。 標準エラー を出力することができます ( 2> ) の中のコマンドの標準入力に送る。 >(...) .
    に加えて bashzsh , ksh もサポートしています。 原則的に からのリダイレクトと組み合わせることはできません。 標準エラー というのは、ここで行われているように ( 2> >(...) ) は、黙って無視されるようです ( ksh 93u+ ).

    • grep -v 'Permission denied' フィルター アウト ( -v から)すべての行を find というフレーズを含む、コマンドの標準エラーストリーム。 Permission denied に出力し、残りの行を標準エラー出力に出力します ( >&2 ).

    • 注意:ごく稀に grep の出力が find の中のコマンドを待たずに、全体のコマンドが完了するからです。 >(...) を終了させます。で bash を追加することで、これを防ぐことができます。 | cat をコマンドに追加してください。

この手法は

  • 堅牢 : grep にのみ適用されます。 エラーメッセージ (ファイルパスとエラーメッセージの組み合わせではなく、誤検出の可能性があります) また、パーミッション拒否以外のエラーメッセージは、標準エラー出力に渡されます。

  • 副作用なし : find の終了コードは保持されます。遭遇したファイルシステムのアイテムの少なくとも 1 つにアクセスできない場合、終了コード 1 (ただし、これだけではエラー その他 パーミッション拒否以外のものが(も)発生しました。)


POSIX準拠のソリューションです。

完全にPOSIXに準拠したソリューションは、制限があるか、追加の作業が必要です。

もし find の出力は ファイル とにかく (のパイプラインベースの解決策(あるいは完全に抑制されたもの)が必要です。 ジョナサン・レフラー氏の回答 はシンプルで堅牢であり、POSIXに準拠しています。

find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2

リダイレクトの順序が重要であることに注意してください。 2>&1 は必ず 最初に .

標準出力の出力を前もってファイルに取り込んでおくことで 2>&1 を送信します。 だけ のエラーメッセージをパイプラインに流す。 grep を明確に操作することができます。

その 唯一の欠点は 全体の終了コード になります。 grep コマンドの ではなく find この場合の意味は、もし いいえ エラーが発生したり のみ パーミッションが拒否されたエラーの場合、終了コードは 1 (シグナル 失敗 ) 、それ以外の場合 (パーミッション拒否以外のエラー) は 0 - というように、意図とは逆になる。
とはいうものの。 find の終了コードが使われることはほとんどありません。 を超える情報はほとんど伝わらないことが多いので 基本的 存在しないパスを通過するなどの失敗がありました。
しかし、具体的なケースとして、たとえ 一部 入力パスのうち、パーミッションがないためにアクセスできないもの に反映されます。 find の終了コード(GNUとBSDの両方において find に対してパーミッション拒否のエラーが発生した場合。 任意の を処理した場合、終了コードに 1 .

次のバリエーションでそれに対応します。

find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }

ここで、終了コードは、何らかのエラーが発生したかどうかを示します を除いては Permission denied が発生しました。 1 そうであれば 0 それ以外の場合は
言い換えれば、終了コードはコマンドの真の意図を反映するようになりました: 成功 ( 0 ) が報告され、全くエラーがない場合や だけ 許可されないエラーが発生しました。
これは間違いなく、単に find の終了コードを通して、冒頭のソリューションのようになります。


gniourf_gniourf を提案します。(まだ POSIX に準拠していますが) 洗練されたリダイレクトを使用したこのソリューションの一般化 その にファイルパスを表示するデフォルトの動作でも動作します。 標準出力 :

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

要するに、カスタムファイルディスクリプター 3 は、一時的に標準出力を入れ替えるために使用されます ( 1 ) と stderr ( 2 というエラーメッセージが表示されます。 単独 にパイプすることができます。 grep を標準出力で表示します。

これらのリダイレクトを行わない場合、データ(ファイルパス)の両方が エラーメッセージは grep を標準出力で、そして grep を区別することができません。 エラーメッセージ Permission denied と、(仮説)である という名前のファイルには、たまたま というフレーズは Permission denied .

しかし、最初の解決策と同様に、報告される終了コードは、次のようになります。 grep でなく find のようになりますが、上記と同様の修正が可能です。


既存の回答に関する注意事項

  • については、いくつか注意すべき点があります。 マイケル・ブルックス氏の回答 , find . ! -readable -prune -o -print :

    • 必要なのは GNU find 特に、macOSでは動作しません。もちろん、GNUで動作するコマンドだけが必要ならば find このことは、あなたにとって問題ではないでしょう。

    • 一部 Permission denied のエラーが発生することがあります。 今も を表面化させます。 find ! -readable -prune は、このようなエラーを報告します。 を持つディレクトリの項目は、現在のユーザが r パーミッションはあるが x (実行可能)パーミッションがあります。その理由は、ディレクトリ自体が を読み取ることができます。 -prune が実行されず、下降しようとすると への が表示され、エラーメッセージが表示されます。とはいえ 典型的 の場合は r のパーミッションが欠落している。

    • 注:以下の点は、哲学や特定のユースケースの問題であり、あなたには関係ないと判断し、特に単に 印刷 を表示させるだけです。

      • もし をコンセプトにした場合、パーミッションが拒否されたエラーメッセージのフィルタリングは セパレート に適用できるようにしたいタスクです。 任意 find コマンドを使用する場合、その逆のアプローチである積極的に 防止 の中にノイズを入れる必要があります。 find コマンドも複雑化し、論理的な 落とし穴 .
      • 例えば、マイケルの回答に対して最も多く投票されたコメント(この記事を書いている時点では)は、次の方法を示そうと試みています。 拡張する コマンドに -name フィルタを使用します。
        find . ! -readable -prune -o -name '*.txt'
        しかし、これは ではなく は意図したとおりに動作します。なぜなら、末尾の -print アクションは 必須 (に説明があります。 この回答 ). このような微妙な違いがバグを誘発することがあります。
  • の最初の解答は ジョナサン・レフラー氏の回答 , find . 2>/dev/null > files_and_folders と、彼自身が述べているように。 やみくもに黙殺する すべて エラーメッセージ (そして、その回避策は面倒であり、彼も説明しているように完全な堅牢性ではありません)。 実用的に言えば が、しかし、それは 最もシンプルな解決策 というのも、すべてのエラーはパーミッションに関連していると考えてよいからです。

  • ミストの回答 , sudo find . > files_and_folders , は簡潔で実用的ですが、単に 印刷 ファイル名 として実行しているため、セキュリティ上の理由からです。 ルート ユーザは、"find のバグや悪意のあるバージョン、あるいは不正な呼び出しによって、システム全体がめちゃくちゃにされる危険性があります。 トリプルイー ).

  • の2番目の解答は viraptorさんの回答 , find . 2>&1 | grep -v 'Permission denied' > some_file は誤検出の危険性があり (パイプラインで標準出力と標準エラーが混在して送信されるため)、 潜在的に、報告する代わりに -パーミッション拒否のエラーは、標準エラー出力に出力パスと一緒に取り込まれます。