両方のコマンドを試しましたが、コマンドfind | grep "filename"は単純なコマンド。

この動作の適切な説明は何ですか?

コメント

  • あなたすべてのファイルをfindでリストし、データをgrepに渡して処理します。 'でfindを使用すると、リストされているすべてのファイルをgrepに渡して出力を解析する手順がありません。したがって、これはより速くなります。
  • どのような意味で遅くなりますか?コマンドの完了にかかる時間は異なりますか?
  • これをローカルで再現することはできません'。どちらかといえば、time find "$HOME" -name '.profile'time find "$HOME" | grep -F '.profile'よりも長い時間を報告します。 (17秒対12秒)。
  • @JenniferAnderson両方を繰り返し実行しました。 17秒と12秒は平均です。はい、grepのバリエーションはfindの結果のどこにでも一致しますが、find -nameは完全に一致するだけです(この場合)。
  • はい、find filename 高速です。これはタイプミスであり、OPはfind -name filenameを意味していると思いました。 find filenameでは、filenameのみが検査されます(他には何も検査されません)。

回答

(ここではGNU findを想定しています)

使用するだけです

find filename 

は、filenameまたは

ディレクトリの場合、またはその名前が現在のディレクトリに存在しない場合はエラー。これは、ls filenameと同様の非常に迅速な操作です(ただし、filenameがディレクトリの場合は再帰的です)。

In対照的に、

find | grep filename 

は、findすべての名前のリストを生成できるようにします。 grepがフィルタリングする現在のディレクトリ以下。これは明らかに、はるかに遅い操作になります。

実際にはだったと思います。 意図したもの

find . -type f -name "filename" 

これにより、filenameが通常のファイルの名前として検索されます。現在のディレクトリ以下。

これはfind | grep filenameと同じくらい速く(または比較的速く)なりますが、grepソリューションは、-path "*filename*"がivid = “778e7df849″で行うのと同様に、見つかった各名前のフルパスに対してfilenameを照合します。 >


混乱は、は機能します。

ユーティリティはいくつかのパスを取り、これらのパスの下にあるすべての名前を返します。

その後 >ファイル名、パス、タイムスタンプ、ファイルサイズ、ファイルタイプなどに作用する可能性のあるさまざまなテストを使用して、返される名前を制限します。

言うとき

find a b c 

findに、3つのパスaで使用可能なすべての名前をリストするように依頼します。 bおよびc。これらがたまたま現在のディレクトリ内の通常のファイルの名前である場合、これらは返されます。それらのいずれかがディレクトリの名前である場合は、そのディレクトリ内のそれ以降のすべての名前とともに返されます。

実行する場合

find . -type f -name "filename" 

これにより、現在のディレクトリ(.)以下のすべての名前のリストが生成されます。次に、名前を通常のファイルの名前に制限します。つまり、ディレクトリなどではなく、-type fを使用します。次に、-name "filename"を使用してfilenameに一致する名前にさらに制限があります。文字列filenameは、*.txtなどのファイル名グロブパターンである可能性があります(引用することを忘れないでください)。

例:

以下は、私のホームディレクトリで.profileというファイルを「検索」しているようです。

$ pwd /home/kk $ find .profile .profile 

ただし、実際には、パス.profileにあるすべての名前を返すだけです(名前は1つだけで、このファイルのものです)。

次に、cd 1レベル上に移動して、再試行します:

$ cd .. $ pwd /home $ find .profile find: .profile: No such file or directory 

findコマンドは.profileというパスを見つけることができなくなりました。

ただし、現在のディレクトリを確認し、返された名前を.profile のみに制限すると、そこからも:

$ pwd /home $ find . -name ".profile" ./kk/.profile 

コメント

  • find filenameは、filenameのタイプが directory でない場合(またはタイプdirectoryの場合、filenameのみを返します。ただし、エントリ自体はありませんでした)

回答

非技術的な説明:群衆の中でジャックを探しています群衆の中のすべての人を探して、ジャック以外のすべてを考慮から除外するよりも高速です。

コメント

  • 問題は、OPがジャックに期待していることです。群衆の中で唯一の人になります。もしそうなら、彼らは'幸運です。 find jackは、jackというファイルが'の場合、jackを一覧表示します。 >

、またはディレクトリ内のすべての名前(' saディレクトリの場合)。 ' findの仕組みについての誤解です。

回答

まだ問題を理解していませんが、さらに洞察を提供できます。

クサラナンダのようにfind | grep私のシステムでは明らかに高速ですが、あまり意味がありません。最初は、ある種のバッファリングの問題を想定していました。コンソールに書き込むと、次のファイル名を読み取るための次のシステムコールまでの時間が遅くなります。パイプへの書き込みは非常に高速です。32バイトの書き込みでも約40MiB /秒です(私のかなり遅いシステムでは、1MiBのブロックサイズで300MiB /秒)。したがって、findは、パイプ(またはファイル)への書き込み時にファイルシステムからの読み取りを高速化できるため、ファイルパスの読み取りとコンソールへの書き込みの2つの操作を並行して実行できると想定しました(これは、シングルスレッドプロセスとしてのfindだけでは実行できません。

それはfindの障害

2つの呼び出しの比較

:> time find "$HOME"/ -name "*.txt" >/dev/null real 0m0.965s user 0m0.532s sys 0m0.423s 

および

:> time find "$HOME"/ >/dev/null real 0m0.653s user 0m0.242s sys 0m0.405s 

は、findが信じられないほど愚かなことをしていることを示しています(それが何であれ)。 -name "*.txt"の実行にはまったく能力がないことが判明しました。

入力/出力比に依存する可能性があります

書くものがほとんどない場合は、find -nameが勝つと思うかもしれませんが、find -nameはもっと恥ずかしいだけです。 div id = “778e7df849″>

。何も書かなくても失われますgrepの200Kファイル(13Mのパイプデータ)に対して:

time find /usr -name lwevhewoivhol 

findgrepと同じくらい高速ですが、

findnameに対する愚かさは他のテストには及ばないことがわかりました。代わりに正規表現を使用すると、問題は解消されます。

:> time find "$HOME"/ -regex "\.txt$" >/dev/null real 0m0.679s user 0m0.264s sys 0m0.410s 

これはバグと見なすことができると思います。バグレポートを提出してくれる人はいますか?私のバージョンはfind(GNU findutils)4.6.0

コメント

  • タイミングはどの程度再現可能ですか?最初に-nameテストを実行した場合は、ディレクトリの内容がキャッシュされていないため、速度が低下している可能性があります。 (-name-regexをテストすると、少なくともキャッシュ効果が考慮された後は、ほぼ同じ時間がかかることがわかります。もちろん、find …)
  • @psmearsの異なるバージョンである可能性があります。もちろん、私はこれらのテストを数回実行しました。キャッシングの問題は、最初の回答の前の質問へのコメントでも言及されています。私のfindバージョンはfind(GNU findutils)4.6.0
  • -name '*.txt'の追加が遅くなるのはなぜ驚くべきことですかfind?各ファイル名をテストして、追加の作業を行う必要があります。
  • @Barmar一方で、この追加の作業は非常に高速に実行できます。一方、この余分な作業は他の作業を節約します。 findはより少ないデータを書き込む必要があります。また、パイプへの書き込みは非常に遅い操作です。
  • ディスクへの書き込みは非常に遅く、パイプへの書き込みはそれほど悪くはなく、カーネルバッファにコピーするだけです。最初のテストでは、/dev/nullにさらに書き込むと少ないシステム時間が使用されたことに注意してください。

回答

通知:私はあなたが<を意味すると仮定しますdiv id = "189f5af014">

(それ以外の場合は、別のものを探しています。find filenameは、実際には filename というパスを調べます。ファイルがほとんど含まれていない可能性があるため、すぐに終了します)。


5000個のファイルを保持するディレクトリがあるとします。ほとんどのファイルシステムでは、これらのファイルは実際には tree 構造に保存されているため、特定のファイルをすばやく見つけることができます。

したがって、findに、名前を確認するだけでよいファイルを見つけるように依頼すると、find質問します。 > そのファイルの場合、およびそのファイルのみを、大容量記憶装置からごくわずかなページを読み取る基になるファイルシステムに送信します。したがって、ファイルシステムがその価値がある場合、この操作はツリー全体をトラバースしてすべてのエントリを取得するよりもはるかに高速に実行されます。

プレーンなfindを要求するときは、それがまさにあなたが行うことですが、ツリー全体をトラバースして、読み取ります。すべて。単一。エントリ。大きなディレクトリでは、これは問題になる可能性があります(ディスクに大量のファイルを保存する必要があるいくつかのソフトウェアが、2つまたは3つのコンポーネントの深さで「ディレクトリツリー」を作成する理由です。このように、すべてのリーフが保持する必要があるファイルは少なくなります) 。

回答

ファイル/ john / paul / george / ringo / beatlesが存在し、検索しているファイルを想定します。は「ストーン」と呼ばれます

find / stones 

findは「ビートル」を「ストーン」と比較し、「s」と「b」が一致しない場合はドロップします。

find / | grep stones 

この場合、findは「/ john / paul / george / ringo / beatles」をgrepとgrepwilに渡します。一致するかどうかを判断する前に、パス全体を処理する必要があります。

grepははるかに多くの作業を行っているため、時間がかかります

コメント

  • 試してみましたか?
  • 文字列比較のコスト(非常に単純で安価)は、IO(またはキャッシュされている場合はsyscall)のコストによって完全に小さくなります。ディレクトリルックアップの。
  • grep isn ' ta文字列比較、つまり正規表現の比較。つまり、いずれかが見つかるまで文字列全体を処理する必要があります。試合または最後に到達します。ディレクトリルックアップは何があっても同じです。
  • @Paranoidうーん、どのバージョンの find について話しているのですか? 'は、Debianで慣れている find I 'のようなものではないようです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です