Question Python glob plusieurs types de fichiers


Existe-t-il un meilleur moyen d'utiliser glob.glob dans python pour obtenir une liste de plusieurs types de fichiers tels que .txt, .mdown et .markdown? En ce moment j'ai quelque chose comme ça:

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

77
2017-12-31 06:39


origine


Réponses:


Peut-être y a-t-il un meilleur moyen, mais que diriez-vous de:

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

Peut-être y a-t-il une autre façon, alors attendez que quelqu'un d'autre arrive avec une meilleure réponse.


88
2017-12-31 06:53



Enchaîner les résultats:

import itertools as it, glob

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

Alors:

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

28
2018-01-28 14:12



from glob import glob

files = glob('*.gif')
files.extend(glob('*.png'))
files.extend(glob('*.jpg'))

print(files)

Si vous avez besoin de spécifier un chemin, passez en revue les modèles de correspondance et conservez la jointure dans la boucle pour plus de simplicité:

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)

26
2017-10-16 11:23



glob renvoie une liste: pourquoi ne pas simplement l'exécuter plusieurs fois et concaténer les résultats?

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

17
2017-12-29 08:31



avec glob ce n'est pas possible. vous ne pouvez utiliser que:
* correspond à tout
? correspond à n'importe quel caractère
[seq] correspond à n'importe quel caractère de seq
[! seq] correspond à n'importe quel caractère qui n'est pas dans seq

utilisez os.listdir et une expression rationnelle pour vérifier les motifs:

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

13
2017-12-31 07:07



Par exemple, pour *.mp3 et *.flac sur plusieurs dossiers, vous pouvez faire:

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

L'idée peut être étendue à d'autres extensions de fichiers, mais vous devez vérifier que les combinaisons ne correspondent à aucune autre extension de fichier indésirable que vous pourriez avoir sur ces dossiers. Alors, Faites attention avec ça.


4
2018-03-22 23:11



Après être venu ici pour demander de l’aide, j’ai fait ma propre solution et je voulais la partager. Il est basé sur la réponse de user2363986, mais je pense que c'est plus évolutif. Cela signifie que si vous avez 1000 extensions, le code sera toujours élégant.

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

3
2018-02-10 03:13



J'ai libéré Formique qui implémente plusieurs inclus de manière similaire aux Apache Ant ' FileSet et Globs.

La recherche peut être implémentée:

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

Comme le glob Ant complet est implémenté, vous pouvez inclure différents répertoires avec chaque pattern, vous pouvez donc choisir uniquement les fichiers .txt dans un sous-répertoire, et le fichier .markdown dans un autre, par exemple:

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

J'espère que ça aide.


2
2018-05-15 09:30



ne pas glob, mais voici une autre façon d'utiliser une compréhension de liste:

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

2
2017-12-06 03:36



La fonction suivante _glob globs pour plusieurs extensions de fichiers.

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

2
2018-01-15 15:18



Voici la variante de la liste-compréhension d'une ligne de la réponse de Pat (qui inclut également que vous vouliez globaliser dans un répertoire de projet spécifique):

import os, glob
exts = ['*.txt', '*.mdown', '*.markdown']
files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))]

Vous passez en boucle sur les extensions (for ext in exts), puis pour chaque extension, vous prenez chaque fichier correspondant au motif glob (for f in glob.glob(os.path.join(project_dir, ext)).

Cette solution est court, et sans aucune for-loop inutile, liste-compréhension imbriquée ou fonctions pour encombrer le code. Juste pur, expressif, pythonique Zen.

Cette solution vous permet d'avoir une liste personnalisée de exts cela peut être changé sans avoir à mettre à jour votre code. (C'est toujours une bonne pratique!)

La compréhension des listes est la même que celle utilisée dans la solution de Laurent (pour laquelle j'ai voté). Mais je dirais qu’il n’est généralement pas nécessaire de prendre en compte une seule ligne dans une fonction distincte, raison pour laquelle je propose cette solution alternative.

Prime: 

Si vous avez besoin de rechercher non seulement un seul répertoire, mais aussi tous les sous-répertoires, vous pouvez passer recursive=Trueet utiliser le symbole glob multi-directory **  1:

files = [f for ext in exts 
         for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]

Cela invoquera glob.glob('<project_dir>/**/*.txt', recursive=True) et ainsi de suite pour chaque extension.

1 Techniquement, le ** le symbole glob correspond simplement à un ou plusieurs caractères y compris avant-barre oblique  / (contrairement au singulier * symbole de glob). En pratique, il vous suffit de vous rappeler que tant que vous vous entourez ** avec des barres obliques (séparateurs de chemin), elle correspond à zéro ou plusieurs répertoires.


2
2018-05-09 17:13