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


107

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

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

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


回答:


163

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ファイルに返します。この特定のケースで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')]

3
私は見ることができます:glob.glob( '/ path to directory / * / *。txt ")私のために働いています。これは基本的にUnixシェルルールを使用しています
Surya

7
@ User123:ディレクトリを再帰的にリストしません。すべてのテキストファイルを1レベルの深さでリストしていますが、それ以上のサブディレクトリや直接ではありませんpath to directory
Martijn Pieters

1
これは完全に関連recursive=Falseして**/ いるわけではありませんが、機能と一緒に設定すると、特定のフォルダーだけでなく、その子にあるファイルのリストが提供されないのはなぜですか?
Dr_Zaszuś

@Dr_Zaszuś:ごめんなさい?パターンがで終わるため、現在の作業ディレクトリ内**/ディレクトリ名のリストが表示さ/recursive=Falseます。基本的に*、と同じように一致するdoubleがあり、*/効率が低下します。
Martijn Pieters

@Dr_Zaszuś:*/*すべてのサブディレクトリにあるすべてのファイルが必要な場合に使用します。
Martijn Pieters

22

直下のサブディレクトリでファイルを検索するには:

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

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

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つずつ取得できます)。


はい、私はそれを理解しました。しかしglob()、ディレクトリのパターンをサポートすることも期待していませんでした。
Martijn Pieters

コメントが削除されました。間違った印象を与えたことがわかりました。さらに、パッチには**再帰ケースのドキュメントの更新が含まれています。ただし、**機能させるには、スイッチを設定する必要ありますrecursion=True
Martijn Pieters

20

このトピックについては多くの混乱があります。私がそれを明確にできるかどうか見てみましょう(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.


1
これが一番の答えになるはずです!
Abhik Sarkar



4

以下は、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

したがって、次のdir構造がある場合

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ファイル名だけではなく、ファイル名全体でほとんどのパターンが一致します。


2

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

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

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

2

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

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

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

0

Martijnが指摘したように、globは**Python 3.5で導入された演算子を介してのみこれを行うことができます。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

このコマンドrglobは、ディレクトリ構造の最も深いサブレベルまで無限に再帰します。ただし、深さを1レベルだけにする場合は、使用しないでください。

OPがglob.globの使用について話していることを理解しています。これは、すべてのサブフォルダーを再帰的に検索するという意図に応えると思います。

このrglob関数は最近、フォルダー構造をデータの読み取り順序の固定仮定として使用していたデータ処理アルゴリズムの速度を100倍向上させました。ただし、rglob指定した親ディレクトリ以下のすべてのファイルを1回スキャンして、ファイル名をリスト(100万個を超えるファイル)に保存し、そのリストを使用して、どのファイルを開く必要があるかを判断できました。ファイルの命名規則のみに基づいて、またはそれらがどのフォルダーにあったかに基づいて、将来的にポイントします。

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