環境でシェル コマンドを実行することが許可されている場合 (およびスクリプトを *nix で実行していると仮定した場合)、ネイティブの grep コマンドを再帰的に呼び出すことができます。それが最速の結果をもたらします。
$contents_list = array("xyz","abc","hello");
$path = "/tmp/";
$pattern = implode('\|', $contents_list) ;
$command = "grep -r '$pattern' $path";
$output = array();
exec($command, $output);
foreach ($output as $match) {
echo $match . '\n';
}
disable_functions
ディレクティブが有効で、grep を呼び出すことができない場合は、各行で strpos を使用して、ファイルを行ごとに読み取り、アプローチを使用できますRecursiveDirectoryIterator
。strpos
には厳密な等価性チェック (!== false
の代わりに使用) が必要であることに注意してください!= false
。そうしないと、行頭の一致がスキップされます。
少し高速な方法は、glob を再帰的に使用してファイルのリストを取得し、それらのファイルを行ごとにスキャンする代わりに一度に読み取ることです。私のテストによると、このアプローチは、あなたのアプローチよりも約 30 ~ 35% 時間のアドバンテージが得られます。
function recursiveDirList($dir, $prefix = '') {
$dir = rtrim($dir, '/');
$result = array();
foreach (glob("$dir/*", GLOB_MARK) as &$f) {
if (substr($f, -1) === '/') {
$result = array_merge($result, recursiveDirList($f, $prefix . basename($f) . '/'));
} else {
$result[] = $prefix . basename($f);
}
}
return $result;
}
$files = recursiveDirList($path);
foreach ($files as $filename) {
$file_content = file($path . '/' . $filename);
foreach ($file_content as $line) {
foreach($contents_list as $content) {
if(strpos($line, $content) !== false) {
echo $line . '\n';
}
}
}
}
再帰グロブ関数の功績はhttp://proger.i-forge.net/3_ways_to_recursively_list_all_files_in_a_directory/Opcにあります
要約すると、パフォーマンスに関して次のランキングがあります (2 つの一般的なテキスト パターンを使用して、約 1200 個のファイルを再帰的に含む非常に大きなディレクトリの結果を数秒で表示します)。
- exec() 経由で grep を呼び出す - 2.2015s
- -9.4443sで再帰的
glob
および読み取りファイルを使用するfile()
- -15.1183s
RecursiveDirectoryIterator
でファイルを使用および読み取りreadline()