Как я могу искать подпапки с помощью glob.модуль glob в Python?
Я хочу открыть ряд вложенных папок в папке и найти некоторые текстовые файлы и распечатать некоторые строки текстовых файлов. Я использую это:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
но это не может получить доступ к вложенных папок. Кто-нибудь знает, как я могу использовать ту же команду для доступа к подпапкам?
9 ответов:
в Python 3.5 и новее используйте новый рекурсивный
**/
функции:configfiles = glob.glob('C:/Users/sam/Desktop/file1/**/*.txt', recursive=True)
, когда
recursive
установлено,**
с последующим разделителем пути соответствует 0 или более подкаталогов.в более ранних версиях Python,
glob.glob()
невозможно рекурсивно перечислять файлы в подкаталогах.в таком случае я бы использовал
os.walk()
в сочетании сfnmatch.filter()
вместо:import os import fnmatch path = 'C:/Users/sam/Desktop/file1' configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in fnmatch.filter(files, '*.txt')]
это будет ходить ваши каталоги рекурсивно и верните все абсолютные пути к соответствию
.txt
файлы. В этом конкретные случаеfnmatch.filter()
может быть излишним, вы также можете использовать
на glob2 пакет поддерживает Дикие карты и достаточно быстро
code = ''' import glob2 glob2.glob("files/*/**") ''' timeit.timeit(code, number=1)
на моем ноутбуке она занимает около 2 секунд, чтобы соответствовать > 60 000 путей к файлам.
для поиска файлов в непосредственных подкаталогах:
configfiles = glob.glob(r'C:\Users\sam\Desktop\*\*.txt')
для рекурсивной версии, которая пересекает все подкаталоги, вы можете использовать
**
и передатьrecursive=True
начиная с Python 3.5:configfiles = glob.glob(r'C:\Users\sam\Desktop\**\*.txt', recursive=True)
оба вызова функции возвращают списки. Вы могли бы использовать
glob.iglob()
для возврата пути один за другим. Или использоватьpathlib
:from pathlib import Path path = Path(r'C:\Users\sam\Desktop') txt_files_only_subdirs = path.glob('*/*.txt') txt_files_all_recursively = path.rglob('*.txt') # including the current dir
оба метода возвращают итераторы (вы можете получить пути один за другим).
можно использовать Муравьиная С Python 2.6
import formic fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")
раскрытие-я являюсь автором этого пакета.
вот адаптированная версия, которая позволяет
glob.glob
как функциональность без использованияglob2
.def find_files(directory, pattern='*'): if not os.path.exists(directory): raise ValueError("Directory not found {}".format(directory)) matches = [] for root, dirnames, filenames in os.walk(directory): for filename in filenames: full_path = os.path.join(root, filename) if fnmatch.filter([full_path], pattern): matches.append(os.path.join(root, filename)) return matches
Итак, если у вас есть следующая структура dir
tests/files ├── a0 │ ├── a0.txt │ ├── a0.yaml │ └── b0 │ ├── b0.yaml │ └── b00.yaml └── a1
вы можете сделать что-то подобное
files = utils.find_files('tests/files','**/b0/b*.yaml') > ['tests/files/a0/b0/b0.yaml', 'tests/files/a0/b0/b00.yaml']
очень много
fnmatch
шаблон соответствует всему имени файла, а не только имени файла.
configfiles = glob.glob('C:/Users/sam/Desktop/**/*.txt")
не работает для всех случаев, вместо этого используйте glob2
configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt")
Если вы можете установить пакет glob2...
import glob2 filenames = glob2.glob("C:\top_directory\**\*.ext") # Where ext is a specific file extension folders = glob2.glob("C:\top_directory\**\")
все имена файлов и папок:
all_ff = glob2.glob("C:\top_directory\**\**")
если вы используете Python 3.4+, вы можете использовать
pathlib
модуль. ЭлементPath.glob()
метод поддерживает**
pattern, что означает "этот каталог и все подкаталоги, рекурсивно". Он возвращает генератор, дающийPath
объекты для всех соответствующих файлов.from pathlib import Path configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")