2010-12-31 6 views
65

Gibt es eine bessere Möglichkeit, glob.glob in Python zu verwenden, um eine Liste mit mehreren Dateitypen wie .txt, .mdown und .markdown zu erhalten? Im Moment habe ich so etwas wie dieses:Python glob mehrere Dateitypen

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

Antwort

81

Vielleicht gibt es einen besseren Weg, aber wie wäre es:

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

Vielleicht gibt es eine andere Art und Weise ist, so warten, falls jemand anderes mit einem besseren kommt Antworten.

+6

'files_grabbed = [glob.glob (e) für e in [ '* .pdf', '* CPP']]' – Novitoll

+4

Novitoll Lösung ist kurz, aber es endet verschachtelte Erstellen von Listen auf. – robroc

+4

Sie könnten das immer tun;) '[f für f_ in [glob.glob (e) für e in ('* .jpg', '* .mp4')] für f in f_]' – AlexG

8

mit glob ist es nicht möglich. Sie können nur verwenden:
* entspricht allem
?
für ein einzelnes Zeichen [f] alle Zeichen in Seq Spiele
[Seq!] Jedes Zeichen nicht in Seq

Verwendung os.listdir und einen regulären Ausdruck Muster zu überprüfen:

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

beenden Sie Ihre Regex mit $ nur das Ende der Dateinamen zu passen – ThiefMaster

+0

Ich mag diesen Ansatz - wenn Globs Ausdruckskraft nicht mächtig genug ist, upgraden Sie zu einem leistungsfähigeren Regex-System, hacken Sie nicht mit z 'itertools', weil nachfolgende Musteränderungen auch hacky sein müssen (sagen Sie, dass Sie Groß- und Kleinschreibung zulassen wollen). Oh, und es könnte sauberer sein, zu schreiben ". * \. (Txt | sql)" – metakermit

+0

Gibt es einen Grund, os.listdir ('.') Über glob.iglob ('*. *') Vorzuziehen? –

22

Kette der Ergebnisse:

import itertools as it, glob 

def multiple_file_types(*patterns): 
    return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns) 

Dann:

for filename in multiple_file_types("*.txt", "*.sql", "*.log"): 
    # do stuff 
+10

glob.glob -> glob.iglob, damit die Iteratorenkette vollständig faul ausgewertet wird – rodrigob

0

Sie können versuchen, eine manuelle Liste zu erstellen, die die Erweiterung von bestehenden mit denen vergleicht, die Sie benötigen.

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

Ich habe Formic veröffentlicht, die mehrere enthält Apache Ant FileSet and Globs in ähnlicher Weise implementiert.

Die Suche kann realisiert werden:

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 

Da die volle Ant glob implementiert ist, können Sie verschiedene Verzeichnisse mit jedem Muster enthalten, so dass Sie nur die TXT-Dateien in einem Unterverzeichnis wählen könnten, und das. Abschrift in einem anderen, zum Beispiel:

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

Ich hoffe, das hilft.

2

Nicht glob, aber hier ist eine andere Möglichkeit, eine Liste Verständnis mit:

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

Die folgende Funktion _glob Klackse für mehrere Dateierweiterungen.

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) 

Wenn Sie einen Pfad angeben müssen, Schleife über Match-Muster und halten die innerhalb der Schleife der Einfachheit halber verbinden:

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

Diese Arbeiten sollten:

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

Nachdem ich hier um Hilfe gebeten hatte, machte ich meine eigene Lösung und wollte sie teilen. Es basiert auf der Antwort von user2363986, aber ich denke, das ist besser skalierbar.Das heißt, wenn Sie 1000 Erweiterungen haben, wird der Code immer noch etwas elegant aussehen.

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

könnten Sie Filter verwenden:

import os 
import glob 

projectFiles = filter(
    lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] 
    glob.glob(os.path.join(projectDir, "*")) 
) 
1

Dies ist ein Python 3.4+ pathlib Lösung:

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("~")) 

auch ignoriert sie alle Namen Datei mit ~ starten.

10

glob gibt eine Liste zurück: warum nicht einfach mehrmals hintereinander ausführen und die Ergebnisse verketten?

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

Dies ist möglicherweise die am besten lesbare Lösung. Ich würde den Fall von "ProjectFiles" zu "ProjectFiles" ändern, aber großartige Lösung. –

3

Zum Beispiel für *.mp3 und *.flac auf mehreren Ordnern können Sie tun:

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

Die Idee kann auf mehr Dateierweiterungen erweitert werden, aber Sie überprüfen, dass die Kombinationen stimmen nicht mit anderen unerwünschten Dateierweiterungen überein, die Sie möglicherweise in diesen Ordnern haben. Also, sei vorsichtig mit diesem.

0

könnten Sie auch reduce() wie so verwenden:

import glob 
file_types = ['*.txt', '*.mdown', '*.markdown'] 
project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types)) 

diese erstellt eine Liste von glob.glob() für jedes Muster und reduziert sie auf eine einzige Liste.

1

Ein Einzeiler, gerade für die Hölle der es ..

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] 

Ausgang:

['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat'] 
1

Um glob mehrere Typen Datei, Sie muss glob() Funktion aufrufen mehrmals in einer Schleife. Da diese Funktion eine Liste zurückgibt, müssen Sie die Listen verketten.

Zum Beispiel diese Funktion die Arbeit machen:

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

Einfache Nutzung:

project_dir = "path/to/project/dir" 
for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')): 
    print(path) 

Sie auch glob.iglob() verwenden einen Iterator zu haben:

Return ein Iterator die ergibt dieselben Werte wie glob(), ohne sie alle gleichzeitig zu speichern.

def iglob_filetypes(root_dir, *patterns): 
    return (path 
      for pattern in patterns 
      for path in glob.iglob(os.path.join(root_dir, pattern))) 
0

One glob, viele Erweiterungen ... aber unvollkommene Lösung (möglicherweise andere Dateien übereinstimmen).

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)