回答:
私はこれが古いスレッドであることを知っていますが、それを偶然find
見つけて、非バイナリファイルのみを見つけるために使用する非常に高速な方法であることがわかった自分のメソッドを共有したいと思いました。
find . -type f -exec grep -Iq . {} \; -print
-I
grep のオプションは、バイナリファイルをすぐに無視するように指示し.
ます。オプションと一緒に使用すると、-q
テキストファイルとすぐに一致するため、非常に高速になります。スペースが気になる場合は-print
、-print0
にパイプするためにをに変更できxargs -0
ます(ヒントに感謝、@ lucas.werkmeister!)
また、最初のドットはfind
OS Xなどの特定のBSDバージョンの場合にのみ必要ですが、これをエイリアスなどに入れても、常にそこにあるだけでは何の問題もありません。
編集:@ruslanが正しく指摘したように、-and
暗黙のうちに省略できます。
find -type f -exec grep -Iq . {} \; -and -print
して、ファイルをに保持するという利点もありますfind
。テキストファイルに対してのみ実行される-print
別の-exec
ものに置き換えることができます。(grep
ファイル名を印刷させた場合、改行を含むファイル名を区別できなくなります。)
find . -type f -exec grep -Il . {} +
はるかに高速です。欠点は、-exec
@ lucas.werkmeisterが示唆するように、他のユーザーが拡張できないことです
なぜ使いにくいのですか?頻繁に使用する必要があり、毎回入力する必要がない場合は、bash関数を定義するだけです。
function findTextInAsciiFiles {
# usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text
}
それをあなたの中に入れて、.bashrc
ただ走ってください:
findTextInAsciiFiles your_folder "needle text"
いつでも好きなときに。
EDIT OPの編集を反映します:
MIME情報を切り出す場合は、MIME情報をフィルターで除外するステージをパイプラインに追加するだけです。これは、前に来るものだけ取ることで、トリックを行う必要があります:
。cut -d':' -f1
:
function findTextInAsciiFiles {
# usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text | cut -d ':' -f1
}
file
マニュアルから:「ユーザーは、ディレクトリ内のすべての読み取り可能なファイルに「テキスト」という単語が印刷されていることを知っていることに依存しています。」
/proc/meminfo
、/proc/cpuinfo
などのテキストファイルですが、file /proc/meminfo
言います/proc/meminfo: empty
。「テキスト」に加えて「空」もテストする必要があるかどうか疑問に思いますが、他のタイプも「空」を報告できるかどうかはわかりません。
find . -type f -print0 | xargs -0 file | grep -P text | cut -d: -f1 | xargs grep -Pil "search"
残念ながら、これはスペースの節約にはなりません。これをbashスクリプトに入れると、少し簡単になります。
これはスペースセーフです:
#!/bin/bash
#if [ ! "$1" ] ; then
echo "Usage: $0 <search>";
exit
fi
find . -type f -print0 \
| xargs -0 file \
| grep -P text \
| cut -d: -f1 \
| xargs -i% grep -Pil "$1" "%"
text.bin
どうなりますか?2.ファイル名に:
?が含まれている場合はどうなりますか?
これはどう:
$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable'
ファイルタイプなしのファイル名が必要な場合は、最後のsed
フィルターを追加するだけです。
$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'
-e 'type'
最後のgrep
コマンドにオプションを追加することで、不要なファイルタイプを除外できます。
編集:
ご使用のxargs
バージョンが-d
オプションをサポートしている場合、上記のコマンドはより簡単になります。
$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'
私はヒストネスの答えに関して2つの問題を抱えています:
テキストファイルのみを一覧表示します。要求どおりに実際に検索することはありません。実際に検索するには、
find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 grep "needle text"
それは非常に遅いすべてのファイルのgrepプロセスを生成します。より良い解決策は
find . -type f -print0 | xargs -0 grep -IZl . | xargs -0 grep "needle text"
または単に
find . -type f -print0 | xargs -0 grep -I "needle text"
上記のソリューション(2.5GBデータ/ 7700ファイル)では、4秒と比較して0.2秒しかかかりません。つまり、20倍高速です。
また、代替案としてag、Silver Searcher、またはack-grepを引用した人はいません。これらのいずれかが利用可能な場合、それらははるかに優れた代替手段です。
ag -t "needle text" # Much faster than ack
ack -t "needle text" # or ack-grep
最後の注意として、誤検知に注意してください(テキストファイルとして取得されたバイナリファイル)。私はすでにgrep / ag / ackのいずれかを使用して誤検知していたので、ファイルを編集する前に、最初に一致したファイルをリストすることをお勧めします。
古い質問ですが、この情報が答えの質を高めると思います。
実行可能ビットが設定されているファイルを無視するときは、次のコマンドを使用します。
find . ! -perm -111
再帰的に他のディレクトリに入らないようにするには:
find . -maxdepth 1 ! -perm -111
パイプで多くのコマンドを混在させる必要はありません。強力な単純なfindコマンドだけです。
とはいえ、これが誰にとっても役立つことを願っています。
私はこのようにしています:1)ファイルが多すぎる(〜30k)ため、検索することができないため、以下のコマンドを使用して、crontabを介して使用するテキストファイルリストを毎日生成します。
find /to/src/folder -type f -exec file {} \; | grep text | cut -d: -f1 > ~/.src_list &
2).bashrcに関数を作成します。
findex() {
cat ~/.src_list | xargs grep "$*" 2>/dev/null
}
次に、以下のコマンドを使用して検索を実行できます。
findex "needle text"
HTH :)
これは、私のような初心者が1行に複数のコマンドを配置する方法を学習しようとしている人のための、拡張された説明付きの簡略版です。
問題を段階的に書き出すと、次のようになります。
// For every file in this directory
// Check the filetype
// If it's an ASCII file, then print out the filename
これを実現するために、我々は3つのUNIXコマンドを使用することができますfind
、file
とgrep
。
find
ディレクトリ内のすべてのファイルをチェックします。
file
ファイルタイプが表示されます。私たちのケースでは、「ASCIIテキスト」の戻りを探しています。
grep
からの出力でキーワード「ASCII」を探します file
では、これらを1行にまとめる方法を教えてください。これには複数の方法がありますが、疑似コードの順に実行するのが最も理にかなっています(特に私のような初心者にとって)。
find ./ -exec file {} ";" | grep 'ASCII'
複雑に見えますが、分解すると悪くありません。
find ./
=このディレクトリ内のすべてのファイルを調べます。このfind
コマンドは、「式」に一致するファイルのファイル名、またはパスの後に続くもの(この場合は現在のディレクトリまたは./
理解する最も重要なことは、その最初のビットの後のすべてがTrueまたはFalseとして評価されることです。Trueの場合、ファイル名が印刷されます。そうでない場合、コマンドは次に進みます。
-exec
=このフラグは、他のコマンドの結果を検索式として使用できるようにするfindコマンド内のオプションです。関数内で関数を呼び出すようなものです。
file {}
=内で呼び出されるコマンドfind
。このfile
コマンドは、ファイルのファイルタイプを示す文字列を返します。通常、次のようになりますfile mytextfile.txt
。この例では、find
コマンドが参照しているファイルを使用するため、中括弧{}
を挿入して空の変数またはパラメーターとして機能させます。つまり、ディレクトリ内のすべてのファイルの文字列を出力するようにシステムに要求するだけです。
";"
=これは必須find
であり、-exec
コマンドの最後の句読点です。を実行して必要な場合の詳細については、「find」のマニュアルを参照してくださいman find
。
| grep 'ASCII'
= |
はパイプです。パイプは左側にあるものの出力を受け取り、右側にあるものへの入力としてそれを使用します。find
コマンドの出力(単一ファイルのファイルタイプである文字列)を取得し、文字列が含まれているかどうかをテストします'ASCII'
。そうであれば、trueを返します。
現在、コマンドがtrueを返すfind ./
と、右側の式grep
はtrueを返します。出来上がり。
のfile
ユーティリティと組み合わせた素晴らしいユーティリティを使用して、マジックバイトで任意のファイルタイプを見つけることに興味がある場合find
、これは便利です。
$ # Let's make some test files
$ mkdir ASCII-finder
$ cd ASCII-finder
$ dd if=/dev/urandom of=binary.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.009023 s, 116 MB/s
$ file binary.file
binary.file: data
$ echo 123 > text.txt
$ # Let the magic begin
$ find -type f -print0 | \
xargs -0 -I @@ bash -c 'file "$@" | grep ASCII &>/dev/null && echo "file is ASCII: $@"' -- @@
出力:
file is ASCII: ./text.txt
凡例:$
コマンドを入力するインタラクティブなシェルプロンプトです
&&
他のスクリプトを呼び出したり、他の何かをインラインで実行したりするために後の部分を変更できます。つまり、そのファイルに特定の文字列が含まれている場合は、ファイル全体をキャットするか、その中の2番目の文字列を探します。
説明:
find
ファイルであるアイテムxargs
1つのライナーにラインとして各項目を養うbash
コマンド/スクリプトfile
マジックバイトでファイルのタイプをgrep
チェックし、ASCIIが存在するかどうかを確認します。存在する場合は&&
、次のコマンドが実行された後。find
結果をnull
区切って出力します。これは、スペースとメタ文字を含むファイル名をエスケープするのに適しています。xargs
、-0
オプションを使用しnull
て、それらを分離して読み取り、-I @@
各レコードを取得し、スクリプトをbashする位置パラメータ/引数として使用します。--
for bash
は、bashオプションとして解釈できる-
ようなlike で始まっていても、それが引数であることを保証し-c
ますASCII以外のタイプを見つける必要がある場合はgrep ASCII
、次のように他のタイプに置き換えるだけです。grep "PDF document, version 1.4"
find . -type f -exec grep -Il "" {} \;
ます。