2010-12-31 6 views
65

Есть ли лучший способ использовать glob.glob в python, чтобы получить список из нескольких типов файлов, таких как .txt, .mdown и .markdown? Сейчас у меня есть что-то вроде этого:Python glob несколько типов файлов

projectFiles1 = glob.glob(os.path.join(projectDir, '*.txt')) 
projectFiles2 = glob.glob(os.path.join(projectDir, '*.mdown')) 
projectFiles3 = glob.glob(os.path.join(projectDir, '*.markdown')) 

ответ

81

Может быть, есть лучший способ, но как насчет:

>>> 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 

Возможно, есть другой путь, так что ждать в случае, если кто-то придумывает лучше ответ.

+6

'files_grabbed = [glob.glob (е) при е в [ '* .pdf', '* .cpp']]' Решение – Novitoll

+4

Novitoll короткая, но в конечном итоге создание вложенных списков. – robroc

+4

вы всегда можете это сделать;) '[f для f_ в [glob.glob (e) для e in ('* .jpg', '* .mp4')] для f в f_]' – AlexG

8

с глобусом не возможно. вы можете использовать только:
* соответствует всем
? соответствует любому символу
[далее] соответствует любому символу в последовательности
[далее] соответствует любому символу, не в последовательности

использования os.listdir и регулярное выражение для проверки моделей:

for x in os.listdir('.'): 
    if re.match('.*\.txt|.*\.sql', x): 
    print x 
+6

закончите свое регулярное выражение с помощью $ для соответствия только концам имен файлов – ThiefMaster

+0

Мне нравится этот подход - если выразительность глобала недостаточно эффективна, перейдите на более мощную систему регулярных выражений, не взламывайте ее, например, 'itertools', потому что последующие изменения шаблонов также должны быть хаки (скажем, вы хотите разрешить верхний и нижний регистр). О, и может быть более чисто писать '.. * \. (Txt | sql) '' – metakermit

+0

Есть ли причина предпочесть os.listdir ('. ') Над glob.iglob (' *. * ')? –

22

ЦЕПИ результаты:

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 
+10

glob.glob -> glob.iglob, чтобы цепочка итераторов была полностью ленивой. – rodrigob

0

Вы можете попытаться составить список вручную, сравнивая расширение существующих с теми, которые вам нужны.

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) 
2

Я выпустил Formic, который реализует несколько включает в себя подобным образом к Apache Ant-х FileSet and Globs.

Поиск может осуществляться:

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 Глоб реализован, вы можете включать в себя различные каталоги с каждым шаблоном, так что вы можете выбрать только те файлы .txt в одном подкаталоге, и. уценка в другом, например:

patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ] 

Надеюсь, это поможет.

2

Не glob, но вот еще один способ, используя список понимание:

extensions = 'txt mdown markdown'.split() 
projectFiles = [f for f in os.listdir(projectDir) 
        if os.path.splitext(f)[1][1:] in extensions] 
1

Следующая функция _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") 
21
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) 
-1

Это должно работать:

import glob 
extensions = ('*.txt', '*.mdown', '*.markdown') 
for i in extensions: 
    for files in glob.glob(i): 
     print (files) 
3

Придя сюда за помощью, я сделал свое решение и хотел поделиться им. Он основан на ответе 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 
0

Вы можете использовать фильтр:

import os 
import glob 

projectFiles = filter(
    lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] 
    glob.glob(os.path.join(projectDir, "*")) 
) 
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("~")) 

Также игнорирует все имена файлов, начинающиеся с ~.

10

glob возвращает список: почему бы не просто запустить его несколько раз и не конкатенировать результаты?

from glob import glob 
ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown') 
+0

Возможно, это наиболее читаемое решение. Я бы изменил случай 'ProjectFiles' на' projectFiles', но отличное решение. –

3

Например, для *.mp3 и *.flac на несколько папок, вы можете сделать:

mask = r'music/*/*.[mf][pl][3a]*' 
glob.glob(mask) 

Идея может быть расширена до более расширений файлов, но вы должны проверить, что комбинации не будут соответствовать никакому другому нежелательному расширению файла, которое вы можете иметь в этих папках. Итак, будьте осторожны с.

0

Вы также можете использовать 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() для каждого образца и уменьшает их в единый список.

1

Однострочные, как раз для этого ада ..

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'] 
1

К 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))) 
0

Один Глобы, много расширений ... но несовершенное решение (может соответствовать другим файлам).

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) 
Смежные вопросы