フォルダー内の一連のサブフォルダーを開き、いくつかのテキスト ファイルを見つけて、テキスト ファイルのいくつかの行を印刷したいと考えています。私はこれを使用しています:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
ただし、これはサブフォルダーにもアクセスできません。同じコマンドを使用してサブフォルダーにもアクセスする方法を知っている人はいますか?
フォルダー内の一連のサブフォルダーを開き、いくつかのテキスト ファイルを見つけて、テキスト ファイルのいくつかの行を印刷したいと考えています。私はこれを使用しています:
configfiles = glob.glob('C:/Users/sam/Desktop/file1/*.txt')
ただし、これはサブフォルダーにもアクセスできません。同じコマンドを使用してサブフォルダーにもアクセスする方法を知っている人はいますか?
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')]
直下のサブディレクトリでファイルを検索するには:
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 つずつ取得できます)。
glob2パッケージはワイルドカードをサポートし、かなり高速です
code = '''
import glob2
glob2.glob("files/*/**")
'''
timeit.timeit(code, number=1)
私のラップトップでは、 60,000 を超えるファイル パスを照合するのに約 2 秒かかります。
Formicは Python 2.6 で使用できます
import formic
fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")
開示 - 私はこのパッケージの作者です。
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
ファイル名のみではなく、ファイル名全体でかなりのパターン一致。
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\\**\\**")
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)
。