web-dev-qa-db-ja.com

glob.globモジュールを使用してサブフォルダーを検索するにはどうすればよいですか?

フォルダー内の一連のサブフォルダーを開き、いくつかのテキストファイルを見つけて、テキストファイルのいくつかの行を印刷します。私はこれを使用しています:

configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')

ただし、これはサブフォルダーにもアクセスできません。同じコマンドを使用してサブフォルダーにアクセスする方法を知っている人はいますか?

85
UserYmY

Python 3.5以降では、新しい再帰**/機能を使用します。

configfiles = glob.glob('C:/Users/sam/Desktop/file1/**/*.txt', recursive=True)

recursiveが設定されている場合、**の後にパス区切り文字が続くと、0個以上のサブディレクトリに一致します。

以前のPythonバージョンでは、glob.glob()はサブディレクトリ内のファイルを再帰的にリストできません。

その場合、代わりに os.walk()fnmatch.filter() と組み合わせて使用​​します:

import os
import fnmatch

path = 'C:/Users/sam/Desktop/file1'

configfiles = [os.path.join(dirpath, f)
    for dirpath, dirnames, files in os.walk(path)
    for f in fnmatch.filter(files, '*.txt')]

これにより、ディレクトリが再帰的に調べられ、一致する.txtファイルへのすべての絶対パス名が返されます。このspecificの場合、fnmatch.filter()が過剰である可能性があるため、.endswith()テストを使用することもできます。

import os

path = 'C:/Users/sam/Desktop/file1'

configfiles = [os.path.join(dirpath, f)
    for dirpath, dirnames, files in os.walk(path)
    for f in files if f.endswith('.txt')]
127
Martijn Pieters

直下のサブディレクトリでファイルを見つけるには:

configfiles = glob.glob(r'C:\Users\sam\Desktop\*\*.txt')

すべてのサブディレクトリをトラバースする再帰バージョンの場合、**を使用してrecursive=Trueを渡すことができます Python 3.5以降

configfiles = glob.glob(r'C:\Users\sam\Desktop\**\*.txt', recursive=True)

両方の関数呼び出しはリストを返します。 glob.iglob()を使用して、パスを1つずつ返すことができます。または pathlibを使用

from pathlib import Path

path = Path(r'C:\Users\sam\Desktop')
txt_files_only_subdirs = path.glob('*/*.txt')
txt_files_all_recursively = path.rglob('*.txt') # including the current dir

どちらのメソッドも反復子を返します(パスを1つずつ取得できます)。

17
jfs

glob2 パッケージはワイルドカードをサポートし、かなり高速です

code = '''
import glob2
glob2.glob("files/*/**")
'''
timeit.timeit(code, number=1)

私のラップトップでは、一致するのに約2秒かかります > 60,000ファイルパス

17
megawac

Python 2.6で Formic を使用できます

import formic
fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")

開示-私はこのパッケージの著者です。

8
Andrew Alcock

以下は、glob.globを使用せずにglob2のような機能を有効にする適応バージョンです。

def find_files(directory, pattern='*'):
    if not os.path.exists(directory):
        raise ValueError("Directory not found {}".format(directory))

    matches = []
    for root, dirnames, filenames in os.walk(directory):
        for filename in filenames:
            full_path = os.path.join(root, filename)
            if fnmatch.filter([full_path], pattern):
                matches.append(os.path.join(root, filename))
    return matches

したがって、次のディレクトリ構造がある場合

tests/files
├── a0
│   ├── a0.txt
│   ├── a0.yaml
│   └── b0
│       ├── b0.yaml
│       └── b00.yaml
└── a1

このようなことができます

files = utils.find_files('tests/files','**/b0/b*.yaml')
> ['tests/files/a0/b0/b0.yaml', 'tests/files/a0/b0/b00.yaml']

ほとんどのfnmatchパターンは、ファイル名のみではなく、ファイル名全体で一致します。

3
cevaris

Python 3.4+を実行している場合は、 pathlib モジュールを使用できます。 Path.glob() メソッドは**パターンをサポートします。これは、「このディレクトリとすべてのサブディレクトリを再帰的に」意味します。一致するすべてのファイルに対して Path オブジェクトを生成するジェネレーターを返します。

from pathlib import Path
configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")
2
Eugene Yarmash

configfiles = glob.glob('C:/Users/sam/Desktop/**/*.txt")

すべての場合に機能するわけではなく、代わりにglob2を使用します

configfiles = glob2.glob('C:/Users/sam/Desktop/**/*.txt")
2
NILESH KUMAR

このトピックには多くの混乱があります。それを明確にすることができるかどうかを見てみましょう(Python 3.7):

  1. glob.glob('*.txt') :は、現在のディレクトリの「.txt」で終わるすべてのファイルに一致します
  2. glob.glob('*/*.txt') :1と同じ
  3. glob.glob('**/*.txt') :は、イミディエイトサブディレクトリのみで '.txt'で終わるすべてのファイルに一致しますが、現在のディレクトリには一致しません
  4. glob.glob('*.txt',recursive=True) :1と同じ
  5. glob.glob('*/*.txt',recursive=True) :3と同じ
  6. glob.glob('**/*.txt',recursive=True):は、現在のディレクトリとすべてのサブディレクトリにある「.txt」で終わるすべてのファイルに一致します

そのため、常にrecursive=True.を指定するのが最善です

2
germ

Glob2パッケージをインストールできる場合...

import glob2
filenames = glob2.glob("C:\\top_directory\\**\\*.ext")  # Where ext is a specific file extension
folders = glob2.glob("C:\\top_directory\\**\\")

すべてのファイル名とフォルダー:

all_ff = glob2.glob("C:\\top_directory\\**\\**")  
2
dreab

Martijnが指摘したように、globはPython 3.5で導入された**operatorを介してのみこれを行うことができます。 OPはglobモジュールを明示的に要求したため、以下は同様に動作する遅延評価イテレータを返します

import os, glob, itertools

configfiles = itertools.chain.from_iterable(glob.iglob(os.path.join(root,'*.txt'))
                         for root, dirs, files in os.walk('C:/Users/sam/Desktop/file1/'))

ただし、このアプローチではconfigfilesを1回しか反復できないことに注意してください。複数の操作で使用できる設定ファイルの実際のリストが必要な場合は、list(configfiles)を使用して明示的に作成する必要があります。

0
fxx