Googleで数回検索した結果、思いついたのは次のとおりです。
find my_folder -type f -exec grep -l "needle text" {} \; -exec file {} \; | grep text
これは非常に不便で、MIMEタイプ情報などの不要なテキストを出力します。より良い解決策はありますか?同じフォルダーに多くの画像やその他のバイナリファイルがあり、検索する必要のあるテキストファイルがたくさんあります。
私はこれが古いスレッドであることを知っていますが、偶然見つけて、find
を使用して非バイナリファイルのみを見つける非常に高速な方法であることがわかった私のメソッドを共有すると思いました:
find . -type f -exec grep -Iq . {} \; -print
Grepの-I
オプションは、バイナリファイルをすぐに無視するように指示し、.
オプションと-q
を一緒に使用すると、テキストファイルがすぐに一致するため、非常に高速になります。 -print
を-print0
に変更すると、xargs -0
などにパイプできます。スペースが心配な場合は(ヒント、@ lucas.werkmeisterに感謝します!)
また、最初のドットは、OS Xなどの特定のBSDバージョンのfind
にのみ必要ですが、これをエイリアスまたは何かに入れたい場合、常にそこにあるものを傷つけることはありません。
[〜#〜] edit [〜#〜]:@ruslanが正しく指摘したように、-and
は暗示されているため省略できます。
this SO question に基づく:
grep -rIl "needle text" my_folder
なぜ不便なのですか?頻繁に使用する必要があり、毎回入力したくない場合は、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
}
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" "%"
これはどう:
$ 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|:[^:]*$||'
最後のgrep
コマンドに-e 'type'
オプションを追加することで、不要なファイルタイプを除外できます。
編集:
xargs
バージョンが-d
オプションをサポートしている場合、上記のコマンドはよりシンプルになります。
$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'
Histumnessの答えには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のいずれかを使用して誤検知していました。そのため、ファイルを編集する前に、一致したファイルを最初にリストすることをお勧めします。
これが私がやった方法です...
1ファイルがプレーンテキストistextかどうかをテストする小さなスクリプトを作成します。
#!/bin/bash
[[ "$(file -bi $1)" == *"file"* ]]
2。前と同じように検索を使用します
find . -type f -exec istext {} \; -exec grep -nHi mystring {} \;
これを行う別の方法:
# find . |xargs file {} \; |grep "ASCII text"
空のファイルも必要な場合:
# find . |xargs file {} \; |egrep "ASCII text|empty"
これは古い質問ですが、この情報は、ここでの回答の質を高めると思います。
ファイルを無視するとき実行可能ビットを使用して設定すると、このコマンドを使用します。
find . ! -perm -111
他のディレクトリに再帰的に入らないようにするには:
find . -maxdepth 1 ! -perm -111
多くのコマンドを混合するためのpipesは不要で、強力なプレーン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
これを実現するには、find
、file
、およびgrep
の3つのUNIXコマンドを使用できます。
find
は、ディレクトリ内のすべてのファイルをチェックします。
file
はファイルタイプを提供します。私たちの場合、「ASCIIテキスト」の戻り値を探しています
grep
は、file
からの出力でキーワード 'ASCII'を探します
これらを1行にまとめるにはどうすればよいでしょうか?それを行うには複数の方法がありますが、擬似コードの順序でそれを行うのが最も理にかなっています(特に私のような初心者にとって)。
find ./ -exec file {} ";" | grep 'ASCII'
複雑に見えますが、分解しても悪くはありません。
find ./
=このディレクトリ内のすべてのファイルを調べます。 find
コマンドは、 'expression'に一致する任意のファイルのファイル名、またはパスの後にあるもの(この場合は現在のディレクトリまたは./
)を出力します
理解する最も重要なことは、最初のビット以降はすべてTrueまたはFalseとして評価されることです。 Trueの場合、ファイル名が出力されます。そうでない場合、コマンドは続行します。
-exec
=このフラグはfindコマンド内のオプションであり、他のコマンドの結果を検索式として使用できます。関数内で関数を呼び出すようなものです。
file {}
= find
内で呼び出されるコマンド。 file
コマンドは、ファイルのファイルタイプを示す文字列を返します。通常、次のようになります:file mytextfile.txt
。私たちの場合、find
コマンドで表示されているファイルを使用するため、中括弧{}
を入れて空の変数またはパラメーターとして機能させます。つまり、ディレクトリ内のすべてのファイルに対して文字列を出力するようにシステムに要求しているだけです。
";"
=これはfind
で必要であり、-exec
コマンドの最後の句読点です。 man find
を実行して必要な場合の詳細については、「find」のマニュアルを参照してください。
| grep 'ASCII'
= |
はパイプです。パイプは、左側にあるものの出力を取得し、右側にあるものへの入力として使用します。 find
コマンド(単一ファイルのファイルタイプである文字列)の出力を取得し、文字列'ASCII'
が含まれているかどうかをテストします。存在する場合、trueを返します。
現在、grep
コマンドがtrueを返す場合、find ./
の右側の式は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
凡例:$
は、コマンドを入力する対話型のシェルプロンプトです
&&
の後の部分を変更して、他のスクリプトを呼び出すか、インラインで他の処理を行うことができます。つまり、そのファイルに特定の文字列が含まれる場合、ファイル全体をcatするか、その中の2番目の文字列を探します。
説明:
find
ファイルであるアイテムxargs
が各アイテムを1行のライナーとしてフィードするbash
コマンド/スクリプトfile
はマジックバイトでファイルの種類をチェックし、grep
はASCIIが存在する場合、&&
の後に次のコマンドが実行されるかどうかをチェックします。find
は結果を出力しますnull
で区切られます。これは、スペースとメタ文字を含むファイル名をエスケープするのに適しています。xargs
は、-0
オプションを使用して、null
で区切って読み取り、-I @@
は各レコードを取得し、bashスクリプトの位置パラメーター/引数として使用します。--
for bash
は、bashオプションとして解釈される可能性のある-
のような-c
で始まる場合でも、引数の後に来るものはすべて保証しますASCII以外のタイプを見つける必要がある場合は、grep ASCII
をgrep "PDF document, version 1.4"
などの他のタイプに置き換えるだけです
私はxargsが好きです
find . -type f | xargs grep -I "needle text"
ファイル名がおかしい場合は、-0オプションを使用して検索します。
find . -type f -print0 | xargs -0 grep -I "needle text"