Я получаю массив путей (в сочетании с настройками по умолчанию и пользовательскими настройками) и мне нужно выполнить рекурсивный поиск некоторых файлов данных, которые могут быть скрыты между десятками тысяч файлов в любом из этих путей.
Я делаю рекурсивный поиск с RecursiveDirectoryIterator
но это довольно медленно и предлагаемая альтернатива exec("find")
еще медленнее. Чтобы сэкономить время, ввод / вывод и вычислительную мощность, я хотел бы заранее выполнить некоторую предварительную обработку, чтобы избежать многократного поиска в деревьях каталогов и вычисления наименьшего общего знаменателя из заданных путей. Буду признателен за любые советы о том, как это сделать.
Подвох заключается в том, что любой из данных путей может быть не только предком других или просто символической ссылкой друг на друга, но может быть задан как реальный путь или путь к символической ссылке. По крайней мере, можно предположить, что не будет никаких кружащихся символических ссылок (хотя проверка не будет плохой).
Мне нужно реализовать это в PHP, и я набросал следующий код, который еще не охватывает все случаи.
// make all given paths absolute and resolve symlinks
$search_paths = array_map( function($path) {
return realpath( $path ) ?: $path;
}, $search_paths );
// remove all double entries
$search_paths = array_unique( $search_paths );
// sort by length of path, shortest first
usort($search_paths, function($a, $b) {
return strlen($a) - strlen($b);
});
// iterate over all paths but the last
for ( $i = 0; $i < count( $search_paths ) - 1; $i++ ) {
// iterate over all paths following the current
for ( $j = $i; $j < count( $search_paths ); $j++ ) {
if ( strpos ( $search_paths[$j], $search_paths[$i] ) === 0 ) {
// longer path starts with shorter one, thus it's a child. Nuke it!
unset( $search_paths[$j] );
}
}
}
Где этот код не хватает:
Вообразите эти пути в $search_paths
/e/f
/a/b/c/d
/e/f/g/d
с /e/f/g/d
будучи символической ссылкой на /a/b/c/d
,
Код выше оставил бы эти два:
/e/f
/a/b/c/d
но в поисках /e/f
будет на самом деле достаточно, так как он охватывает /a/b/c/d
через символическую ссылку /e/f/g/d
, Это может звучать как крайний случай, но на самом деле вполне вероятно в моей ситуации.
Хитрый, а?
Я уверен, что я не единственный, кто столкнулся с этой проблемой, но я не смог найти решение с помощью Google. Может быть, я просто не понимаю правильную формулировку проблемы.
Спасибо за чтение этого далеко! 🙂
Задача ещё не решена.
Других решений пока нет …