Быстро проверить наличие подкаталогов в списке - PullRequest
0 голосов
/ 18 мая 2018

У меня есть два набора путей, возможно, 5000 файлов в первом наборе и 10000 файлов во втором. Первый набор содержится во втором наборе. Мне нужно проверить, является ли какая-либо из записей во втором наборе дочерней по отношению к какой-либо записи в первом наборе (то есть, если это подкаталог или файл в другом каталоге из первого набора). Есть несколько дополнительных требований:

  • Никаких операций в файловой системе, это должно быть сделано только со строками пути (за исключением работы с символическими ссылками, если необходимо).
  • Независимо от платформы (например, верхний / нижний регистр, различные разделители)
  • Он должен быть устойчивым по отношению к различным способам выражения одного и того же пути.
  • Он должен иметь дело как с символическими ссылками, так и с их целями.
  • Некоторые пути будут абсолютными, а некоторые относительными.
  • Это должно быть как можно быстрее!

Я думаю о том, как получить os.path.abspath() и os.path.realpath() для каждой записи, а затем сравнить их с os.path.commonpath([parent]) == os.path.commonpath([parent, child]). Я не могу придумать хороший способ бежать так быстро, хотя. Или безопасно просто сравнивать строки напрямую? Это сделало бы это намного легче. Спасибо!

РЕДАКТИРОВАТЬ: Я был немного неясным о независимости платформы. Он должен работать для всех платформ, но не будет, например, смешанных путей в стиле Windows и Unix.

1 Ответ

0 голосов
/ 18 мая 2018

Вы можете сначала вычислить реальный путь всех путей, используя os.path.realpath, а затем использовать os.path.commonprefix, чтобы проверить, является ли один путь в потомке первого набора путей.

Пример:

import os

first = ['a', 'b/x', '/r/c']
second = ['e', 'b/x/t', 'f']

first = set(os.path.realpath(p) for p in first)
second = set(os.path.realpath(p) for p in second)

for s in second:
    if any(os.path.commonprefix([s, f]) == f
           for f in first):
        print(s)

Вы получаете:

/full/path/to/b/x/t
...