Python glob несколько типов файлов
есть ли лучший способ использовать glob.glob в python, чтобы получить список из нескольких типов файлов, таких как .формат txt. ,mdown все, а .уценка? Прямо сейчас у меня есть что-то вроде этого:
projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') )
projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') )
projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') )
25 ответов:
может быть, есть лучший способ, но как насчет:
>>> import glob >>> types = ('*.pdf', '*.cpp') # the tuple of file types >>> files_grabbed = [] >>> for files in types: ... files_grabbed.extend(glob.glob(files)) ... >>> files_grabbed # the list of pdf and cpp filesвозможно, есть другой способ, поэтому подождите, если кто-то другой придумает лучший ответ.
from glob import glob files = glob('*.gif') files.extend(glob('*.png')) files.extend(glob('*.jpg')) print(files)Если вам нужно указать путь, цикл по шаблонам соответствия и сохранить соединение внутри цикла для простоты:
from os.path import join from glob import glob files = [] for ext in ('*.gif', '*.png', '*.jpg'): files.extend(glob(join("path/to/dir", ext))) print(files)
цепи результаты:
import itertools as it, glob def multiple_file_types(*patterns): return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns)затем:
for filename in multiple_file_types("*.txt", "*.sql", "*.log"): # do stuff
globвозвращает список: почему бы просто не запустить его несколько раз и объединить результаты?from glob import glob ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown')
С glob это невозможно. вы можете использовать только:
* соответствует все
? соответствует любому одиночному символу
[далее] соответствует любому символу в seq
[!сл] соответствует любому символу, не в seqиспользовать ОС.listdir и регулярное выражение для проверки модели:
for x in os.listdir('.'): if re.match('.*\.txt|.*\.sql', x): print x
например,
*.mp3и*.flacна нескольких папках, вы можете сделать:mask = r'music/*/*.[mf][pl][3a]*' glob.glob(mask)идея может быть расширена до большего количества расширений файлов,но вы должны проверить, что комбинации не будут соответствовать любому другому нежелательному расширению файла, которое вы можете иметь в этих папках. Итак,будьте осторожны С этим.
после того, как я пришел сюда за помощью, я сделал свое собственное решение и хотел поделиться им. Он основан на ответе user2363986, но я думаю, что это более масштабируемо. Это означает, что если у вас есть 1000 расширений, код все равно будет выглядеть несколько элегантно.
from glob import glob directoryPath = "C:\temp\*." fileExtensions = [ "jpg", "jpeg", "png", "bmp", "gif" ] listOfFiles = [] for extension in fileExtensions: listOfFiles.extend( glob( directoryPath + extension )) for file in listOfFiles: print(file) # Or do other stuff
я выпустил Муравьиная который реализует несколько включает в себя аналогично Apache Ant в файлы и шаблоны.
поиск может быть реализован:
import formic patterns = ["*.txt", "*.markdown", "*.mdown"] fileset = formic.FileSet(directory=projectDir, include=patterns) for file_name in fileset.qualified_files(): # Do something with file_nameпоскольку реализован полный Ant glob, вы можете включать разные каталоги с каждым шаблоном, поэтому вы можете выбрать только те .txt файлов в одном подкаталоге, а .уценка в другом, например:
patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ]Я надеюсь, что это помогает.
не
glob, но вот еще один способ использования понимания списка:extensions = 'txt mdown markdown'.split() projectFiles = [f for f in os.listdir(projectDir) if os.path.splitext(f)[1][1:] in extensions]
следующая функция
_globглобусы для нескольких расширений файлов.import glob import os def _glob(path, *exts): """Glob for multiple file extensions Parameters ---------- path : str A file name without extension, or directory name exts : tuple File extensions to glob for Returns ------- files : list list of files matching extensions in exts in path """ path = os.path.join(path, "*") if os.path.isdir(path) else path + "*" return [f for files in [glob.glob(path + ext) for ext in exts] for f in files] files = _glob(projectDir, ".txt", ".mdown", ".markdown")
вот однострочный список-вариант понимания ответа Пэта (который также включает в себя то, что вы хотели glob в определенном каталоге проекта):
import os, glob exts = ['*.txt', '*.mdown', '*.markdown'] files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))]вы перебираете расширения (
for ext in exts), а затем для каждого расширения вы берете каждый файл, соответствующий шаблону glob (for f in glob.glob(os.path.join(project_dir, ext)).данное решение короче, и без каких-либо ненужных для-циклов, вложенных списков или функций для загромождения кода. Просто чистый, выразительный, питонический Дзэн.
это решение позволяет вам иметь пользовательский список
extsэто может быть изменено без необходимости обновления кода. (Это всегда хорошая практика!)список-понимание то же самое используется в решении Лорана (за которое я голосовал). Но я бы сказал, что обычно нет необходимости выделять одну строку в отдельную функцию, поэтому я предоставляю это в качестве альтернативы решение.
бонус:
Если вам нужно искать не только один каталог, но и все подкаталоги, вы можете пройти
recursive=Trueи использовать мульти-каталог Глоб символ**1:files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]появится
glob.glob('<project_dir>/**/*.txt', recursive=True)и так далее для каждого расширения.1 технически
**символ глобуса просто соответствует одному или нескольким символам в том числе косая черта/(в отличие от единственного числа*символ Глоб). На практике вам просто нужно помнить, что пока вы окружаете**С прямыми косыми чертами (разделители пути), он соответствует нулю или более каталогов.
Это в Python 3.4+
pathlibустранение:exts = ".pdf", ".doc", ".xls", ".csv", ".ppt" filelist = (str(i) for i in map(pathlib.Path, os.listdir(src)) if i.suffix.lower() in exts and not i.stem.startswith("~"))также он игнорирует все имена файлов, начиная с
~.
один лайнер, просто для ада..
folder = "C:\multi_pattern_glob_one_liner" files = [item for sublist in [glob.glob(folder + ext) for ext in ["/*.txt", "/*.bat"]] for item in sublist]выход:
['C:\multi_pattern_glob_one_liner\dummy_txt.txt', 'C:\multi_pattern_glob_one_liner\dummy_bat.bat']
до
globнесколько типов файлов, вам нужно позвонитьglob()функции несколько раз в цикле. Поскольку эта функция возвращает список, необходимо объединить списки.например, эта функция выполняет задание:
import glob import os def glob_filetypes(root_dir, *patterns): return [path for pattern in patterns for path in glob.glob(os.path.join(root_dir, pattern))]простое использование:
project_dir = "path/to/project/dir" for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')): print(path)вы также можете использовать
glob.iglob()иметь итератор:возвращает итератор, который дает те же значения, что и glob (), фактически не сохраняя их все одновременно.
def iglob_filetypes(root_dir, *patterns): return (path for pattern in patterns for path in glob.iglob(os.path.join(root_dir, pattern)))
вы можете попробовать сделать ручной список, сравнивая расширение существующих с теми, которые вам нужны.
ext_list = ['gif','jpg','jpeg','png']; file_list = [] for file in glob.glob('*.*'): if file.rsplit('.',1)[1] in ext_list : file_list.append(file)
вы можете использовать фильтр:
import os import glob projectFiles = filter( lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] glob.glob(os.path.join(projectDir, "*")) )
вы также можете использовать
reduce()вот так:import glob file_types = ['*.txt', '*.mdown', '*.markdown'] project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types))это создает список из
glob.glob()для каждого шаблона и сводит их к одному списку.
import os import glob import operator from functools import reduce types = ('*.jpg', '*.png', '*.jpeg') lazy_paths = (glob.glob(os.path.join('my_path', t)) for t in types) paths = reduce(operator.add, lazy_paths, [])https://docs.python.org/3.5/library/functools.html#functools.reduce https://docs.python.org/3.5/library/operator.html#operator.add
один шар, много расширений... но несовершенное решение (может соответствовать другим файлам).
filetypes = ['tif', 'jpg'] filetypes = zip(*[list(ft) for ft in filetypes]) filetypes = ["".join(ch) for ch in filetypes] filetypes = ["[%s]" % ch for ch in filetypes] filetypes = "".join(filetypes) + "*" print(filetypes) # => [tj][ip][fg]* glob.glob("/path/to/*.%s" % filetypes)
У меня была такая же проблема и вот что я придумал
import os, sys, re #without glob src_dir = '/mnt/mypics/' src_pics = [] ext = re.compile('.*\.(|{}|)$'.format('|'.join(['png', 'jpeg', 'jpg']).encode('utf-8'))) for root, dirnames, filenames in os.walk(src_dir): for filename in filter(lambda name:ext.search(name),filenames): src_pics.append(os.path.join(root, filename))
например:
import glob lst_img = [] base_dir = '/home/xy/img/' # get all the jpg file in base_dir lst_img += glob.glob(base_dir + '*.jpg') print lst_img # ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg'] # append all the png file in base_dir to lst_img lst_img += glob.glob(base_dir + '*.png') print lst_img # ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg', '/home/xy/img/3.png']функция:
import glob def get_files(base_dir='/home/xy/img/', lst_extension=['*.jpg', '*.png']): """ :param base_dir:base directory :param lst_extension:lst_extension: list like ['*.jpg', '*.png', ...] :return:file lists like ['/home/xy/img/2.jpg','/home/xy/img/3.png'] """ lst_files = [] for ext in lst_extension: lst_files += glob.glob(base_dir+ext) return lst_files
используйте список расширений и повторите
from os.path import join from glob import glob files = ['*.gif', '*.png', '*.jpg'] for ext in files: files.extend(glob(join("path/to/dir", ext))) print(files)
Это Должно Работать:
import glob extensions = ('*.txt', '*.mdown', '*.markdown') for i in extensions: for files in glob.glob(i): print (files)
Comments