一度にすべてのディレクトリを検索するときに問題が発生しますgrep
。次のコマンドを使用すると、
find . -name "*.txt" | xargs grep texthere
時間がかかりすぎて、「そのようなファイルまたはディレクトリはありません」というエラーが表示されます。
なぜこのようなことが起こるのでしょうか。また、これより簡単な方法はないのでしょうかgrep
。それとも、間違ったコマンドを使用しているのでしょうか。
答え1
GNU grep をお持ちの場合は、@Ouroborus が提案しているように、grep 自体が再帰的に検索するための "-r" オプションをサポートしています。
残念ながら、SunOS のように grep がそのようなオプションをサポートしていない場合は、代わりに次のコマンドを使用できます。
find . -name "*.txt" -exec grep -n your_pattern {} /dev/null \;
/dev/null
grep を実行するたびに 2 つのファイル (一致するファイル *.txt と /dev/null) が提供されるようにするためのトリッキーが追加され、検索対象のファイルの名前が強制的に印刷されます。また、-type f
のオプションを追加しfind
て、のスコープを絞り込むことができますfind
。
答え2
例えばこの答え、おそらく次の方が良いでしょう:
grep -rnw '/path/to/somewhere/' -e "pattern"
-r
または-R
再帰的である、-n
は行番号であり、-w
単語全体に一致します。-l
(小文字の L) を追加すると、一致するファイルのファイル名のみを指定できます。
答え3
権限に関するエラーが発生している場合 (エラーが発生しているとは言っていません)、ルート ディレクトリ ( ) か、または や など/
、すべてのファイルを読み取る権限がないパスのいずれかにいると思われます。ただし、非常に長い時間がかかるとのことなので、最初の仮定 (ルート ディレクトリ) の可能性が高いと思います。/etc
/var
絶対に検索したい場合全てファイル全体システムに関しては、あなたがやっていることはほぼ正しいです。意思何をしても時間がかかります。検索するファイルが多すぎるのです。
find
表示するファイルの量を絞り込むために使用できます。
現時点では、
$ find . -name "*.txt" | xargs grep texthere
プレーンテキスト ファイルのみに関心があるようなので、他の種類のファイル (実行可能ファイル) を除外できます。
$ find / -type f \! -perm -o=x -name "*.txt" | xargs grep texthere
ここ.
で置き換えました。/
考えるそうです(間違っていたら訂正してください)。また、私はファイル(-type f
)は実行不可能( \! -perm -o=x
) (!
シェルがおかしな動作をしないようにエスケープする必要があります)。
さて、私たちにできることはあと2つあります。1つは安全に関すること、もう1つはおそらく速度が少し向上します。
ファイル名の中にはスペースや、通常はファイル名に使用したくない奇妙な文字が含まれている場合があります。これらを適切に渡すためにfind
、grep
$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 grep texthere
この ( ) は、各ファイル名がスペース文字ではなく文字 ( )-print0
で区切られることを意味します。これらを-delimited ファイル名として受け取るための の対応するオプションはです。nul
\0
xargs
nul
-0
これら 2 つのオプションを使用していないため、「そのようなファイルまたはディレクトリはありません」というエラーが発生すると考えられます。
速度の問題は です。これは、検索文字列が正規表現を含まないプレーンテキスト文字列である場合に使用する とfgrep
まったく同じユーティリティです。grep -F
したがって、プレーンテキスト文字列があり、それをシステム全体のすべてのファイルで検索したい場合は、次のようにします。
$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 fgrep texthere
権限の問題... 明らかに、読み取れないファイルがあります。それらの前にfind
を追加しfgrep
て実行できますsudo
:
$ sudo find ... | xargs -0 sudo fgrep texthere
-perm
または、別のフラグを作成してfind
(また、入力できないディレクトリを無視するようにすることもできます)、時間がかかりすぎて、コマンド ラインが非常に長くなるため、ここでは行いません。
または、ルート シェルを取得してそこから実行することもできますsudo -s
が、これは一般的にお勧めしません。なぜなら、人々は自分が であることを忘れてシステムを台無しにする傾向があるからですroot
。
別の解決策システム全体のlocate
すべてのファイルを検索するには、このコマンドを使用します。このコマンドはファイル階層を検索するのではなく、データベースを使用します(データベースは通常毎日更新されるため、.txt
locate
全てファイルはそこにあるかもしれません)。データベースには、すべてのユーザーがアクセスできるディレクトリ内のファイルのみが含まれるため、自分のディレクトリの読み取り権限を削除した場合、ファイルはそこに存在しません。
したがって、上記のコマンドをほぼ同等のfind
コマンドに置き換えます。locate
$ locate '*.txt' -0 | xargs -0 fgrep texthere
オプション-0
(または--null
一部のシステムでは)--print0
は のオプションに対応しますfind
。