Python glob複数のファイルタイプ


142

Pythonでglob.globを使用して、.txt、.mdown、.markdownなどの複数のファイルタイプのリストを取得するより良い方法はありますか?現在、私はこのようなものを持っています:

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

回答:


156

多分もっと良い方法がありますが、どうですか:

import glob
types = ('*.pdf', '*.cpp') # the tuple of file types
files_grabbed = []
for files in types:
    files_grabbed.extend(glob.glob(files))

# files_grabbed is the list of pdf and cpp files

おそらく別の方法があるので、他の誰かがより良い答えを思い付くのを待ってください。


19
files_grabbed = [glob.glob(e) for e in ['*.pdf', '*.cpp']]
Novitoll 2016年

10
Novitollのソリューションは短いですが、ネストされたリストを作成することになります。
robroc 2017年

9
あなたはいつでもこれを行うことができます;)[f for f_ in [glob.glob(e) for e in ('*.jpg', '*.mp4')] for f in f_]
AlexG

1
files_grabbed = [ glob.glob(e)for e in [' .pdf'、 '* .cpp']]
florisla

3
これは、ファイルのリストを2回ループします。最初の反復では* .pdfをチェックし、2番目の反復では* .cppをチェックします。1回の反復でそれを実行する方法はありますか?結合状態を毎回確認しますか?
リドゥヴァルシャン

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

45

glob リストを返します:何回も実行して結果を連結しないのはなぜですか?

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

3
これはおそらく、最も読みやすいソリューションです。のケースをProjectFilesに変更しprojectFilesますが、素晴らしい解決策です。
ハンスゴールドマン

40

結果を連鎖させる:

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

13
イテレータチェーンが完全に遅延評価されるようにglob.glob-> glob.iglob
rodrigob 2013

1
私は同じ解決策を見つけましたが、知りませんでしたchain.from_iterable。したがって、これは似ていますが、読みにくくなりますit.chain(*(glob.iglob(pattern) for pattern in patterns))
florisla

17

拡張機能の数だけグロブすることを示唆する非常に多くの答えがあるので、代わりに1回だけグロブすることをお勧めします。

from pathlib import Path

files = {p.resolve() for p in Path(path).glob("**/*") if p.suffix in [".c", ".cc", ".cpp", ".hxx", ".h"]}

15

グロブでは不可能です。のみ使用できます:
*すべてに一致します
か?単一の文字に一致
[seq]はseqの任意の文字に一致
[!seq]はseqにない任意の文字に一致

os.listdirと正規表現を使用してパターンを確認します。

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

10
ファイル名の最後のみに一致するように正規表現を$で終了する
ThiefMaster

1
私はこのアプローチが好きです-グロブの表現力が十分に強力でない場合は、より強力な正規表現システムにアップグレードしてください。たとえばitertools、後続のパターン変更もハックする必要があるため(たとえば、大文字と小文字を許可したい場合)、ハックしないでください。 。おお、そしてそれは書く方がきれいかもしれない'.*\.(txt|sql)'
metakermit 2013

os.listdir好む何らかの理由がある( ' ')glob.iglob上で(' ')?
Mr.WorshipMe 2016

14

たとえば、用*.mp3および*.flac複数のフォルダに、あなたが行うことができます。

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

アイデアは、より多くのファイル拡張子に拡張することができ、しかし、あなたは組み合わせは、あなたがそれらのフォルダに持つかもしれない他の不要なファイル拡張子と一致しないことを確認する必要があります。したがって、これには注意してください。

拡張子の任意のリストを単一のグロブパターンに自動的に組み合わせるには、次のようにします。

mask_base = r'music/*/*.'
exts = ['mp3', 'flac', 'wma']
chars = ''.join('[{}]'.format(''.join(set(c))) for c in zip(*exts))
mask = mask_base + chars + ('*' if len(set(len(e) for e in exts)) > 1 else '')
print(mask)  # music/*/*.[fmw][plm][3a]*

6

ワンライナー、まさにそのために...

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

4

ここに助けを求めて来た後、私は自分の解決策を作り、それを共有したいと思いました。これは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

私にはうまくいきません。私が使用するdirectoryPath = "/Users/bla/bla/images_dir*."
NeStack 2018

これをデバッグするにはさらに情報が必要です...例外が発生していますか?また、Windowsを使用している場合、そのパスは機能するようには見えません(ドライブ文字がない)。
ハンスゴールドマン

4
files = glob.glob('*.txt')
files.extend(glob.glob('*.dat'))

4
良い答えは、コードのいくつかの説明と、おそらくコードの背後にあるあなたの推論のいくつかを提供します。
SunSparc

4

PythonのデフォルトグロブはBashのグロブに実際には従いませんが、他のライブラリでこれを行うことができます。wcmatchのglobで中括弧を有効にすることができます。

>>> from wcmatch import glob
>>> glob.glob('*.{md,ini}', flags=glob.BRACE)
['LICENSE.md', 'README.md', 'tox.ini']

好みに応じて、拡張グロブパターンを使用することもできます。

from wcmatch import glob
>>> glob.glob('*.@(md|ini)', flags=glob.EXTGLOB)
['LICENSE.md', 'README.md', 'tox.ini']

これはrecursive旗を取らない
Shamoon

@Shamoonいいえ、glob.GLOBSTARフラグがかかります
facelessuser

3

Apache AntのFileSetおよびGlobsと同様の方法で複数のインクルードを実装するFormicをリリースしました

検索を実装できます。

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グロブが実装されているため、パターンごとに異なるディレクトリを含めることができます。たとえば、次のように、1つのサブディレクトリで.txtファイルのみを選択し、別のサブディレクトリで.markdownを選択できます。

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

これがお役に立てば幸いです。


3

以下の関数_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")

3

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

また、で始まるすべてのファイル名を無視します~


3

以下は、パットの回答の1行のリスト理解バリアントです(これには、特定のプロジェクトディレクトリにグロブしたいことも含まれます)。

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))に一致する各ファイルを取得します。

このソリューションは短く、不要なforループ、ネストされたリスト内包表記、またはコードを乱雑にする関数はありません。純粋で表現力豊かなPythonic Zenです。

このソリューションではexts、コードを更新しなくても変更可能なカスタムリストを作成できます。(これは常に良い習慣です!)

リスト内包表記は、ローランのソリューションで使用したものと同じです(私が投票しました)。しかし、通常は1行を個別の関数に分解する必要はないと主張します。そのため、これを代替ソリューションとして提供しています。

ボーナス:

単一のディレクトリだけでなくすべてのサブディレクトリも検索する必要がある場合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技術的には、**グロブ記号は、単一のグロブ記号とは異なり、スラッシュを含む 1つ以上の文字に一致します。実際には、スラッシュ(パス区切り文字)で囲まれている限り、0個以上のディレクトリと一致することを覚えておく必要があります。/***


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

既存の拡張子と必要な拡張子を比較して、手動のリストを作成してみてください。

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)


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

1

拡張機能のリストを使用して反復する

from os.path import join
from glob import glob

files = []
extensions = ['*.gif', '*.png', '*.jpg']
for ext in extensions:
   files.extend(glob(join("path/to/dir", ext)))

print(files)

0

あなたはフィルターを使うことができます:

import os
import glob

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

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()パターンごとにリストが作成され、それらが単一のリストに削減されます。


0

1つのグロブ、多くの拡張子...しかし不完全なソリューション(他のファイルと一致する場合があります)。

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)

0

私は同じ問題を抱えていましたが、これが私が思いついたものです

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

0

さらに別の解決策(glob複数の一致を使用してパスを取得patternsreduce、and を使用してすべてのパスを1つのリストに結合するために使用add):

import functools, glob, operator
paths = functools.reduce(operator.add, [glob.glob(pattern) for pattern in [
    "path1/*.ext1",
    "path2/*.ext2"]])

0

使用する場合、これをpathlib試してください:

import pathlib

extensions = ['.py', '.txt']
root_dir = './test/'

files = filter(lambda p: p.suffix in extensions, pathlib.Path(root_dir).glob('**/*'))

print(list(files))

0

私が経験的なテストから得た結果からglob.glob、拡張子によってファイルを除外するのに適した方法ではないことがわかりました。その理由のいくつかは次のとおりです。

  • グロビング「言語」では、複数の拡張子を完全に指定することはできません。
  • 前者の場合、ファイル拡張子によっては不正な結果が得られます。
  • グロビング方式は、他のほとんどの方式よりも遅いことが経験的に証明されています。
  • 奇妙なことですが、他のファイルシステムオブジェクトにも「拡張子」、フォルダも含めることができます。

私は(正しいことと時間内の効率性のために)次の4さまざまな方法をテストして、拡張子によってファイルをフィルターで除外し、それらをに入れましたlist

from glob import glob, iglob
from re import compile, findall
from os import walk


def glob_with_storage(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = glob(globs, recursive=True)

    return results


def glob_with_iteration(args):

    elements = ''.join([f'[{i}]' for i in args.extensions])
    globs = f'{args.target}/**/*{elements}'
    results = [i for i in iglob(globs, recursive=True)]

    return results


def walk_with_suffixes(args):

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            for e in args.extensions:
                if ff.endswith(e):
                    results.append(path_join(r,ff))
                    break
    return results


def walk_with_regs(args):

    reg = compile('|'.join([f'{i}$' for i in args.extensions]))

    results = []
    for r, d, f in walk(args.target):
        for ff in f:
            if len(findall(reg,ff)):
                results.append(path_join(r, ff))

    return results

私のラップトップで上記のコードを実行すると、次の自動説明的な結果が得られました。

Elapsed time for '7 times glob_with_storage()':  0.365023 seconds.
mean   : 0.05214614
median : 0.051861
stdev  : 0.001492152
min    : 0.050864
max    : 0.054853

Elapsed time for '7 times glob_with_iteration()':  0.360037 seconds.
mean   : 0.05143386
median : 0.050864
stdev  : 0.0007847381
min    : 0.050864
max    : 0.052859

Elapsed time for '7 times walk_with_suffixes()':  0.26529 seconds.
mean   : 0.03789857
median : 0.037899
stdev  : 0.0005759071
min    : 0.036901
max    : 0.038896

Elapsed time for '7 times walk_with_regs()':  0.290223 seconds.
mean   : 0.04146043
median : 0.040891
stdev  : 0.0007846776
min    : 0.04089
max    : 0.042885

Results sizes:
0 2451
1 2451
2 2446
3 2446

Differences between glob() and walk():
0 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\numpy
1 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Utility\CppSupport.cpp
2 E:\x\y\z\venv\lib\python3.7\site-packages\future\moves\xmlrpc
3 E:\x\y\z\venv\lib\python3.7\site-packages\Cython\Includes\libcpp
4 E:\x\y\z\venv\lib\python3.7\site-packages\future\backports\xmlrpc

Elapsed time for 'main':  1.317424 seconds.

拡張子でファイルをフィルターする最も速い方法は、最も醜い方法ですら起こります。つまり、ネストされたforループとメソッドstringを使用した比較endswith()です。

さらに、ご覧のように、(パターンを使用したE:\x\y\z\**/*[py][pyc])グロビングアルゴリズムは、2拡張子(pyおよびpyc)のみが指定されていても、正しくない結果を返します。


0
import glob
import pandas as pd

df1 = pd.DataFrame(columns=['A'])
for i in glob.glob('C:\dir\path\*.txt'):
    df1 = df1.append({'A': i}, ignore_index=True)
for i in glob.glob('C:\dir\path\*.mdown'):
    df1 = df1.append({'A': i}, ignore_index=True)
for i in glob.glob('C:\dir\path\*.markdown):
    df1 = df1.append({'A': i}, ignore_index=True)

こんにちはSway Wu、ようこそ。説明の追加をご検討ください。
Tiago Martins Peres李大仁

-1

これはうまくいくはずです:

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

-1

例えば:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.