7 ответов:
ОС.гуляй это ответ, это будет найти первый матч:
import os def find(name, path): for root, dirs, files in os.walk(path): if name in files: return os.path.join(root, name)и это будет найти все матчи:
def find_all(name, path): result = [] for root, dirs, files in os.walk(path): if name in files: result.append(os.path.join(root, name)) return resultи это будет соответствовать шаблону:
import os, fnmatch def find(pattern, path): result = [] for root, dirs, files in os.walk(path): for name in files: if fnmatch.fnmatch(name, pattern): result.append(os.path.join(root, name)) return result find('*.txt', '/path/to/dir')
я использовал версию
os.walkи в большем каталоге есть время около 3,5 сек. Я пробовал два случайных решений не большое улучшение, потом просто делал так:paths = [line[2:] for line in subprocess.check_output("find . -iname '*.txt'", shell=True).splitlines()]пока это только POSIX, я получил 0,25 сек.
из этого я считаю, что вполне возможно оптимизировать весь поиск много независимым от платформы способом, но именно здесь я остановил исследование.
Если вы работаете с Python 2 у вас есть проблемы с бесконечной рекурсии на окна вызвано собственн-ссылаясь симлинки.
этот скрипт не будет следовать за ними. Обратите внимание, что это Windows-специфичного!
import os from scandir import scandir import ctypes def is_sym_link(path): # http://stackoverflow.com/a/35915819 FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT) def find(base, filenames): hits = [] def find_in_dir_subdir(direc): content = scandir(direc) for entry in content: if entry.name in filenames: hits.append(os.path.join(direc, entry.name)) elif entry.is_dir() and not is_sym_link(os.path.join(direc, entry.name)): try: find_in_dir_subdir(os.path.join(direc, entry.name)) except UnicodeDecodeError: print "Could not resolve " + os.path.join(direc, entry.name) continue if not os.path.exists(base): return else: find_in_dir_subdir(base) return hitsон возвращает список всех путей, которые указывают на файлы в списке файлов. Использование:
find("C:\", ["file1.abc", "file2.abc", "file3.abc", "file4.abc", "file5.abc"])
для быстрого, независимого от ОС поиска, используйте
scandirhttps://github.com/benhoyt/scandir/#readme
Читать http://bugs.python.org/issue11406 подробнее почему.
посмотреть модуль ОС для ОС.прогулка или ОС.listdir
Смотрите также этот вопрос оС.ходите не копаясь в каталогах ниже пример кода
если вы используете Python на Ubuntu, и вы хотите, чтобы он работал только на Ubuntu, существенно более быстрым способом является использование терминала
locateвот такая программа.import subprocess def find_files(file_name): command = ['locate', file_name] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0] output = output.decode() search_results = output.split('\n') return search_results
search_resultsэтоlistабсолютных путей к файлам. Это в 10 000 раз быстрее, чем методы выше, и для одного поиска я сделал это было ~72 000 раз быстрее.
в Python 3.4 или новее, вы можете использовать pathlib сделать рекурсивный глоббинг:
>>> import pathlib >>> sorted(pathlib.Path('.').glob('**/*.py')) [PosixPath('build/lib/pathlib.py'), PosixPath('docs/conf.py'), PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]Ссылка:https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob
в Python 3.5 или новее, вы также можете сделать рекурсивный глоббинг такой:
>>> import glob >>> glob.glob('**/*.txt', recursive=True) ['2.txt', 'sub/3.txt']Ссылка:https://docs.python.org/3/library/glob.html#glob.glob
Comments