両方のコマンドを試しましたが、このコマンドは find | grep 'filename'
単純なコマンドよりも数倍遅いですfind 'filename'
。
この行動の正しい説明は何ですか?
答え1
(私はfind
これがGNUであると仮定しています)
のみ使用
find filename
会議filename
ディレクトリの場合は内部名のみを返し、現在のディレクトリに名前がない場合はエラーのみを返すため、より高速です。filename
これは非常に高速な操作に似ていますls filename
(ただし、filename
ディレクトリの場合は再帰的です)。
対照的に、
find | grep filename
find
リストを作成できます。みんなこれにより、現在のディレクトリと次のディレクトリの名前がgrep
フィルタリングされます。これは明らかにはるかに遅い作業です。
私が推測するもの実際にもともと目的はこれでした。
find . -type f -name 'filename'
これにより、現在のディレクトリまたは次のディレクトリでfilename
一般ファイルの名前が検索されます。
これは高速または非常に高速ですが、回避策はfind | grep filename
方法と同様に、見つかった各名前のフルパスを一致させることです。grep
filename
-path '*filename*'
find
これらの混乱は、find
物事がどのように機能するかについての誤解から来ています。
このユーティリティには一部が必要です。道このパスの下のすべての名前を返します。
それからあなたはできます限界ファイル名、パス、タイムスタンプ、ファイルサイズ、ファイル形式などで機能できるさまざまなテストから返された名前を使用してください。
言うと
find a b c
find
3つのパスと利用可能な各名前を一覧表示a
するようb
に求められますc
。これが現在ディレクトリにある一般ファイルの名前である場合は、その名前が返されます。そのうちの1つがディレクトリ名の場合は、そのディレクトリ内の他のすべての名前と一緒に返されます。
私がするとき
find . -type f -name 'filename'
.
これにより、現在のディレクトリ()以下のすべての名前のリストが生成されます。-type f
次に、名前の拡張子filename
を-name '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
答え2
非技術的な説明:群衆の中でJackを見つけることは、Jackを除くすべての人を除いて、群衆の中ですべての人を見つけるよりも速いです。
答え3
まだ問題を理解していませんが、より多くの洞察を提供できます。
Kusalanandaのように、find | grep
私のシステムでの呼び出しは確かに高速ですが、これはあまり意味がありません。最初は、ある種のバッファリング問題があると仮定しました。コンソールに書き込むと、次のファイル名を読み取るための次のシステムコールが遅くなりました。パイプへの書き込みは非常に高速です。 32バイト書き込みの場合でも約40MiB / sです(かなり遅いシステムでは1MiBブロックサイズの場合は300MiB / s)。したがって、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
。 200Kファイル(13Mパイプデータ)の場合、書き込み可能な項目がまったくなくても失われますgrep
。
time find /usr -name lwevhewoivhol
find
grep
しかし、次のように高速かもしれません。
find
この愚かさはname
他のテストに拡張されていないことがわかりました。代わりに正規表現を使用すると問題が消えます。
:> time find "$HOME"/ -regex '\.txt$' >/dev/null
real 0m0.679s
user 0m0.264s
sys 0m0.410s
これはバグだと見ることができると思います。バグレポートを提出する意思がある人はいますか?私のバージョンはfind(GNU findutils)4.6.0です。
答え4
/john/paul/george/ringo/beatles ファイルが存在し、検索中のファイルの名前が「stones」であるとします。
find / stones
find は "beatles" を "stones" と比較し、一致しない場合は "s" と "b" を削除します。
find / | grep stones
この場合、 find は "/john/paul/george/ringo/beatles" を grep に渡し、grep が一致することを確認する前にパス全体をナビゲートする必要があります。
したがって、grepはより多くのタスクを実行するので、時間がかかります。