867

許可が拒否されたすべてのメッセージを非表示にする必要があります。

find . > files_and_folders

そのようなメッセージが発生したとき、私は実験しています。それが発生しないすべてのフォルダーとファイルを収集する必要があります。

files_and_foldersアクセス許可レベルをファイルに指示することは可能ですか?

エラーを同時に非表示にするにはどうすればよいですか?

4

20 に答える 20

578

使用する:

find . 2>/dev/null > files_and_folders

これPermission deniedにより、もちろんエラーだけでなく、すべてのエラー メッセージが非表示になります。

シンボリックリンクのホップ数が多すぎるなど、他の可能性のあるエラーを本当に保持したいが、許可が拒否されたものは保持したくない場合は、おそらく「許可が拒否された」と呼ばれるファイルが多くないことを推測する必要があります。そして試してください:

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

標準エラーのみを厳密にフィルタリングしたい場合は、より複雑な構造を使用できます。

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

findコマンドの I/O リダイレクトは次のとおり2>&1 > files_and_folders |です。パイプは標準出力をgrepコマンドにリダイレクトし、最初に適用されます。は、2>&1標準エラーを標準出力と同じ場所 (パイプ) に送信します。は、> files_and_folders標準出力 (標準エラーではない) をファイルに送信します。最終的な結果として、標準エラーに書き込まれたメッセージはパイプを介して送信され、通常の出力がfindファイルに書き込まれます。標準出力をフィルタリングします(grepどの程度選択するかを決定でき、ロケールとO / Sに応じてスペルを変更する必要がある場合があります)および最終>&2残りのエラーメッセージ (標準出力に書き込まれる) がもう一度標準エラーに送られることを意味します。最終的なリダイレクトは端末ではオプションと見なすことができますが、標準エラーにエラー メッセージが表示されるようにスクリプトで使用することをお勧めします。

やりたいことに応じて、このテーマには無限のバリエーションがあります。これは、任意の Bourne シェル派生物 (Bash、Korn など) および任意の POSIX 準拠バージョンの Unix のバリアントで動作しますfind

システムにあるの特定のバージョンに適応させたい場合はfind、別のオプションが利用できる場合があります。特にGNUfindには、他のバージョンでは利用できない無数のオプションがあります。そのようなオプションのセットについては、現在受け入れられている回答を参照してください。

于 2009-04-17T21:57:42.587 に答える
303

ノート:

  • この答えはおそらく、ユースケースが保証するよりも深くなり、find 2>/dev/null多くの状況で十分である可能性があります. クロスプラットフォームの観点と、可能な限り堅牢なソリューションを見つけるためのいくつかの高度なシェル手法の議論については、まだ興味深いかもしれませんが、保護されているケースはほとんど仮説に基づいている可能性があります.

シェルがbashまたはzshの場合、POSIX 準拠の機能のみを使用して、適度にシンプルでありながら堅牢なソリューションがあります。それ自体は POSIX の一部ではありませんが、ほとんどの最新の Unix プラットフォームには POSIX が付属しているため、このソリューションは広く移植可能になっています。findbash

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

ノート:

  • システムがローカライズされたエラー メッセージを表示するように構成されている場合は、find以下の呼び出しの前にLC_ALL=C ( LC_ALL=C find ...) を付けて、英語のメッセージが報告されるようにしgrep -v 'Permission denied'、意図したとおりに機能するようにします。ただし、表示されるエラー メッセージは必ず英語でも表示されます

  • >(...)は、(めったに使用されない)出力 をリダイレクトできる出力プロセス置換です (この場合、 stderr output ( 2>) は、 内のコマンドの stdin です>(...)。およびに
    加えて、原則としてそれらもサポートしますが、それらを からのリダイレクトと組み合わせようとしています。ここ ( ) で行われているstderrは、黙って無視されているように見えます( )。bashzshksh2> >(...)ksh 93u+

    • grep -v 'Permission denied'句を含むすべての行を (コマンドの stderr ストリームから) 除外し ( ) 、残り行を stderr に出力します ( )。-vfindPermission denied>&2

    • 注: の出力の一部が完了後にgrep到着する可能性がわずかにあります。これは、コマンド全体が内部のコマンドの終了を待たないためです。では、コマンドに追加することでこれを防ぐことができます。 find>(...)bash| cat

このアプローチは次のとおりです。

  • Robust :エラー メッセージgrepにのみ適用され(ファイル パスとエラー メッセージの組み合わせには適用されず、誤検知につながる可能性があります)、アクセス許可が拒否されたもの以外のエラー メッセージは stderr に渡されます。

  • side-effect free :findの終了コードは保持されます: 遭遇したファイルシステム項目の少なくとも 1 つにアクセスできないと、終了コードが返されます(ただし、アクセス拒否以外の1エラーが発生したかどうかはわかりません)。


POSIX 準拠のソリューション:

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

の出力をとにかくファイルfindにキャプチャする(または完全に抑制する) 場合、 Jonathan Leffler の回答からのパイプラインベースのソリューションは、シンプルで堅牢で、POSIX に準拠しています。

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

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

stdout 出力を事前にファイルにキャプチャすると、パイプラインを介してエラー メッセージのみ2>&1を送信でき、エラー メッセージは明確に操作できます。grep

唯一の欠点は、全体的な終了コードgrepがではなくコマンドのになることfindです。これは、この場合、エラーがまったくない場合、または許可が拒否されたエラーのみ1の場合、終了コードは(signaling failure ) になり、そうでない場合は (権限が拒否されたもの以外のエラー) 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 準拠の)一般化を提案しています。これは、ファイル パスをstdoutに出力するデフォルトの動作でも機能します

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

つまり、カスタム ファイル記述子を使用して stdout ( ) と stderr ( )3を一時的に交換し、エラー メッセージだけを stdout 経由でパイプすることができます。12grep

これらのリダイレクトがないと、データ (ファイル パス)grepエラー メッセージの両方がstdout 経由でパイプされgrepエラー メッセージ Permission deniedと、名前Permission denied.

ただし、最初の解決策と同様に、報告される終了コードはgrepではなくfindになりますが、上記と同じ修正を適用できます。


既存の回答に関するメモ:

  • Michael Brux の回答については、find . ! -readable -prune -o -print次の点に注意する必要があります。

    • GNU が必要findです。特に、macOS では動作しません。もちろん、 GNU で動作するコマンドだけが必要な場合はfind、これは問題になりません。

    • 一部のPermission deniedエラーは引き続き発生する可能性があります:現在のユーザーがアクセス許可を持っているが、 (実行可能) アクセス許可を欠いているディレクトリの項目find ! -readable -pruneについて、このようなエラーを報告します。その理由は、ディレクトリ自体読み取り可能であり、実行されず、そのディレクトリに降りようとするとエラーメッセージがトリガーされるためです。とはいえ、典型的なケースは許可が欠落している場合です。rx-pruner

    • 注: 次の点は、哲学および/または特定の使用例の問題であり、特にパスを印刷するだけで十分である場合は、それが自分には関係なく、コマンドがニーズに適していると判断する場合があります。

      • パーミッション拒否エラー メッセージのフィルタリングを、任意のコマンドに適用できる別のタスクとして概念化する場合、パーミッション拒否エラーを予防的に防止する反対のアプローチでは、コマンドに「ノイズ」を導入する必要があります。複雑さと論理的な落とし穴 findfind
      • たとえば、Michael の回答に対する最も投票数の多いコメント (この記事の執筆時点) は、次のようにフィルターを含めてコマンドを拡張する方法を示そうとしています: ただし、後続のアクションが必要なため、これは意図したとおりに機能しませ。 (説明はこの回答にあります)。このような微妙な点がバグを引き起こす可能性があります。-name
        find . ! -readable -prune -o -name '*.txt'
        -print
  • Jonathan Leffler の回答の最初の解決策はfind . 2>/dev/null > files_and_folders、彼自身が述べているように、 すべてのエラー メッセージをやみくもに黙らせます(彼も説明しているように、回避策は面倒で、完全には堅牢ではありません)。ただし、実用的に言えば、これが最も簡単な解決策です。すべてのエラーが権限に関連していると想定して満足しているかもしれません。

  • ミストの答えは簡潔sudo find . > files_and_foldersで実用的ですが、セキュリティ上の理由から、単にファイル名を印刷する以外にはお勧めできません: rootユーザーとして実行しているため、「find のバグによってシステム全体が台無しになるリスクがあります。または悪意のあるバージョン、または予想外に何かを書き込む誤った呼び出し。通常の権限でこれを実行した場合は発生しませんでした」(トリプルによるミストの回答に関するコメントから)

  • viraptor's answerの2 番目のソリューションは、find . 2>&1 | grep -v 'Permission denied' > some_file(パイプラインを介して stdout と stderr の混合を送信するため) 誤検知のリスクを冒し、潜在的に、stderr を介して許可拒否エラーを報告する代わりに、出力パスと一緒にそれらをキャプチャします。出力ファイルで。

于 2016-10-31T03:51:28.573 に答える
119

ルート "/" から検索を開始する場合、おそらく次のような出力が表示されます。

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

許可だからです。これを解決するには:

  1. sudo コマンドを使用できます。

    sudo find /. -name 'toBeSearched.file'
    

スーパーユーザーのパスワードを尋ねます。パスワードを入力すると、本当に必要な結果が表示されます。sudo コマンドを使用する権限がない場合、つまりスーパー ユーザーのパスワードを持っていない場合は、まずシステム管理者に依頼して sudoers ファイルに追加してもらいます。

  1. 標準エラー出力を(通常はディスプレイ/画面)からいくつかのファイルにリダイレクトして、画面にエラーメッセージが表示されないようにすることができます。特別なファイル /dev/null にリダイレクトします:

    find /. -name 'toBeSearched.file' 2>/dev/null
    
  2. 標準エラー出力を (通常はディスプレイ/画面) から標準出力 (通常はディスプレイ/画面) にリダイレクトしてから、grep コマンドで -v "invert" パラメータを指定してパイプし、「許可が拒否されました」という出力行が表示されないようにすることができます。単語のペア:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
    
于 2012-02-15T08:27:40.037 に答える
102

私は使用しなければなりませんでした:

find / -name expect 2>/dev/null

見つけたいものの名前を指定し、すべてのエラーを /dev/null にリダイレクトするように指示します

私が探していたexpectプログラムの場所であることを期待してください。

于 2012-02-04T02:29:45.227 に答える
66

2> / dev/nullを使用してパイプstderrします/dev/null

find . -name '...' 2>/dev/null

于 2009-04-17T21:59:16.357 に答える
30

-permまた、述語と述語を使用して、-prune読み取り不能なディレクトリに降りないようにすることもできます ( 「検索プログラムから "許可が拒否された" 出力ステートメントを削除するにはどうすればよいですか? - Unix & Linux Stack Exchangeも参照してください):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
于 2014-03-23T15:08:56.193 に答える
23

標準エラーをリダイレクトします。たとえば、UNIX マシンで bash を使用している場合、次のように標準エラーを /dev/null にリダイレクトできます。

find . 2>/dev/null >files_and_folders
于 2009-04-17T21:57:44.567 に答える
13

これらのエラーは、標準エラー出力(fd 2)に出力されます。それらを除外するには、すべてのエラーを/ dev/nullにリダイレクトするだけです。

find . 2>/dev/null > some_file

または、最初にstderrとstdoutを結合してから、これらの特定のエラーをgrepします。

find . 2>&1 | grep -v 'Permission denied' > some_file
于 2009-04-17T22:00:10.897 に答える
12

簡単な答え:

find . > files_and_folders 2>&-

2>&--標準エラー ファイル記述子 ( ) を閉じる ( 2) ため、すべてのエラー メッセージが表示されなくなります。

  • 1' Permission denied' エラーが表示されない場合でも、終了コードはそのままです。

GNU に対する確実な答えfind:

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

それに追加のオプションを渡します(下に降りることを防ぎます) が、find( ) 権限と権限の両方を持たない ( )ディレクトリ ( )または ( )他のファイル。-prune-print-typed\!-readable-executable-o-print

  • -readable-executableオプションはGNU拡張であり、POSIX標準の一部ではありませ
  • Permission denied異常/破損したファイルで「 」を返す場合があります (たとえば、 v2.0.5 未満を使用しているコンテナーにマウントされたファイルシステムに影響を与えるバグ レポートを参照してください)。lxcfs

POSIX互換find(GNU、OSX/BSDなど)で動作する堅牢な回答

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

パイプラインを使用して標準エラー ストリームを に渡し、文字列grepを含むすべての行を削除し'Permission denied'ます。

LC_ALL=C環境変数を使用してPOSIX ロケールを設定し、ファイル記述子を複製して標準エラー ストリームを にパイプし、によって返されたエラー コードを反転しての元の動作に近づけます。3>&2 2>&1 1>&33>&2 2>&1 grep[ $? = 1 ][]grepfind

  • 出力リダイレクトによるエラーもフィルタリング'Permission denied'します (たとえば、files_and_foldersファイル自体が書き込み可能でない場合) 。
于 2016-12-25T04:17:05.630 に答える
4

アクセス許可が拒否されたという警告だけを回避するには、読み取り不能なファイルを検索から除外して無視するように find に指示します。次のように、式を検索結果に OR として追加します。

find / \! -readable -prune -o -name '*.jbd' -ls

これは主に(読み取り不可能なファイルに一致し、リストから削除する)または( *.jbdのような名前に一致し、それを [ls で] 表示する) と言います。(デフォルトでは、-or を使用しない限り、式は AND で結合されることに注意してください。) 2 番目の式に -ls が必要です。そうしないと、find がいずれかの一致を表示するデフォルト アクションを追加することができます。これにより、すべての読み取り不能ファイルも表示されます。 .

しかし、システム上の実際のファイルを探している場合、多くのファイルがある /dev を調べる理由は通常ありません。そのため、次のように、そのディレクトリを除外する式を追加する必要があります。

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

したがって、(読み取り不可能なファイルに一致し、リストからプルーニングする)または(パス /dev に一致し、リストからプルーニングする)または( *.jbdのようなファイルに一致し、それを表示する)

于 2014-09-16T00:59:49.617 に答える
3

使用する

sudo find / -name file.txt

それはばかげており (検索を昇格させるため)、安全ではありませんが、書くのははるかに短くなります。

于 2014-12-16T11:37:48.253 に答える
2

上記の答えはどれもうまくいきませんでした。私がインターネットで見つけたものはすべて、エラーを隠すことに焦点を当てています。プロセスの return-code / exit-code を適切に処理するものはありません。私は bash スクリプト内でコマンド find を使用して、いくつかのディレクトリを見つけ、その内容を調べます。終了コードを使用して、コマンド検索の成功を評価します。値がゼロの場合は機能し、それ以外の場合は失敗します。

上記のMichael Bruxによる回答が機能する場合があります。しかし、失敗するシナリオが 1 つあります。問題を発見し、自分で修正しました。次の場合にファイルを整理する必要があります。

it is a directory AND has no read access AND/OR has no execute access

ここでの重要な問題は、AND/OR です。私が読んだ良い推奨条件シーケンスは次のとおりです。

-type d ! -readable ! -executable -prune

これは常に機能するとは限りません。これは、一致が次の場合にプルーニングがトリガーされることを意味します。

it is directory AND no read access AND no execute access

読み取りアクセスは許可されているが、実行アクセスは許可されていない場合、この一連の式は失敗します。

いくつかのテストの後、私はそれを認識し、シェル スクリプト ソリューションを次のように変更しました。

nice find /home*/ -maxdepth 5 -follow \
    \( -type d -a ! \( -readable -a -executable \) \) -prune \
    -o \
    \( -type d -a -readable -a -実行可能 -a -name "${m_find_name}" \) -print

ここで重要なのは、結合された式に「正しくない」を配置することです。

has read access AND has execute access

それ以外の場合は、完全なアクセス権がありません。つまり、プルーニングします。これは、以前に提案された解決策が失敗した1つのシナリオでうまくいくことが証明されました。

コメント セクションの質問については、以下の技術的な詳細を提供します。詳細が過度である場合は申し訳ありません。

  • なぜコマンド nice を使用するのですか? ここでアイデアを得ました。最初は、ファイルシステム全体を調べるときにプロセスの優先度を下げるとよいと考えていました。私のスクリプトはいくつかのディレクトリに限定されているため、私には意味がないことに気付きました。-maxdepth を 3 に減らしました。
  • なぜ /home*/ 内を検索するのですか? これは、このスレッドには関係ありません。非特権ユーザー (ルートではない) でソース コードをコンパイルして、すべてのアプリケーションを手動でインストールします。「/home」内にインストールされます。複数のバイナリとバージョンを共存させることができます。すべてのディレクトリを見つけて、マスター/スレーブ方式で検査およびバックアップする必要があります。複数の "/home" (専用サーバー内で複数のディスクを実行) を持つことができます。
  • -follow を使用する理由 ユーザーは、ディレクトリへのシンボリック リンクを作成する場合があります。有用性は依存します。見つかった絶対パスを記録しておく必要があります。
于 2016-12-22T11:06:40.663 に答える
-2

最小限の解決策は、readableフラグを追加することです。

find . -name foo -readable

于 2021-07-08T23:26:25.133 に答える