Если вам разрешено выполнять команды оболочки в вашей среде (и при условии, что вы запускаете свой скрипт на * 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, вы можете использовать свой подход с RecursiveDirectoryIterator
и читать файлы построчно, используя strpos для каждой строки. Обратите внимание, что strpos
требует строгой проверки на равенство (используйте !== false
вместо != false
), иначе вы пропустите совпадения в начале строки.
Немного более быстрый способ — использовать glob recusively для получения списка файлов и читать эти файлы сразу, а не сканировать их построчно. Согласно моим тестам, этот подход даст вам преимущество во времени примерно на 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';
}
}
}
}
Авторство рекурсивной функции glob принадлежит http://proger.i-forge.net/3_ways_to_recursively_list_all_files_in_a_directory/Opc
Подводя итог, с точки зрения производительности у вас есть следующие рейтинги (результаты в секундах для очень большого каталога, содержащего ~ 1200 файлов рекурсивно, с использованием двух распространенных текстовых шаблонов):
- вызов grep через exec() - 2.2015s
- использовать рекурсивный
glob
и читать файлы с file()
- 9,4443 с
- использовать
RecursiveDirectoryIterator
и читать файлы с readline()
- 15,1183 с
person
András Szepesházi
schedule
14.11.2013