Apakah ada cara yang lebih baik untuk menggunakan glob.glob dengan python untuk mendapatkan daftar beberapa jenis file seperti .txt, .mdown, dan .markdown? Sekarang saya memiliki sesuatu seperti ini:
projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') )
projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') )
projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') )
main_file = projectFiles1 + projectFiles2 + projectFiles3
? yang juga akan mengarah ke daftar utama dengan semua jenis dengan penggabunganJawaban:
Mungkin ada cara yang lebih baik, tapi bagaimana dengan:
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
Mungkin ada cara lain, jadi tunggu kalau-kalau ada orang lain yang memberikan jawaban yang lebih baik.
sumber
files_grabbed = [glob.glob(e) for e in ['*.pdf', '*.cpp']]
[f for f_ in [glob.glob(e) for e in ('*.jpg', '*.mp4')] for f in f_]
from glob import glob files = glob('*.gif') files.extend(glob('*.png')) files.extend(glob('*.jpg')) print(files)
Jika Anda perlu menentukan jalur, putar ulang pola kecocokan dan pertahankan gabungan di dalam perulangan untuk kesederhanaan:
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)
sumber
glob
mengembalikan daftar: mengapa tidak menjalankannya beberapa kali dan menggabungkan hasilnya?from glob import glob project_files = glob('*.txt') + glob('*.mdown') + glob('*.markdown')
sumber
ProjectFiles
menjadiprojectFiles
, tapi solusi yang bagus.Rangkai hasilnya:
import itertools as it, glob def multiple_file_types(*patterns): return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns)
Kemudian:
for filename in multiple_file_types("*.txt", "*.sql", "*.log"): # do stuff
sumber
chain.from_iterable
. Jadi ini adalah serupa, tetapi kurang dibaca:it.chain(*(glob.iglob(pattern) for pattern in patterns))
.Begitu banyak jawaban yang menyarankan penggabungan sebanyak jumlah ekstensi, saya lebih suka menggembung sekali saja:
from pathlib import Path files = {p.resolve() for p in Path(path).glob("**/*") if p.suffix in [".c", ".cc", ".cpp", ".hxx", ".h"]}
sumber
dengan glob itu tidak mungkin. Anda hanya dapat menggunakan:
* cocok dengan semuanya
? cocok dengan karakter tunggal
[seq] yang cocok dengan karakter apa pun dalam seq
[! seq] cocok dengan karakter apa pun yang tidak dalam urutan
gunakan os.listdir dan regexp untuk memeriksa pola:
for x in os.listdir('.'): if re.match('.*\.txt|.*\.sql', x): print x
sumber
itertools
karena perubahan pola selanjutnya juga harus diretas (katakanlah Anda ingin mengizinkan huruf besar dan kecil) . Oh, dan mungkin lebih bersih untuk menulis'.*\.(txt|sql)'
Misalnya, untuk
*.mp3
dan*.flac
di beberapa folder, Anda dapat melakukan:mask = r'music/*/*.[mf][pl][3a]*' glob.glob(mask)
Idenya dapat diperluas ke lebih banyak ekstensi file, tetapi Anda harus memeriksa bahwa kombinasi tidak akan cocok dengan ekstensi file yang tidak diinginkan lainnya yang mungkin Anda miliki di folder tersebut. Jadi berhati - hatilah dengan ini.
Untuk secara otomatis menggabungkan daftar sembarang ekstensi ke dalam satu pola glob, Anda dapat melakukan hal berikut:
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]*
sumber
A one-liner, Hanya untuk itu ..
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]
keluaran:
['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat']
sumber
Meskipun glob default Python tidak benar-benar mengikuti setelah glob Bash, Anda dapat melakukannya dengan library lain. Kami dapat mengaktifkan kawat gigi di glob wcmatch .
>>> from wcmatch import glob >>> glob.glob('*.{md,ini}', flags=glob.BRACE) ['LICENSE.md', 'README.md', 'tox.ini']
Anda bahkan dapat menggunakan pola glob yang diperluas jika itu adalah preferensi Anda:
from wcmatch import glob >>> glob.glob('*.@(md|ini)', flags=glob.EXTGLOB) ['LICENSE.md', 'README.md', 'tox.ini']
sumber
recursive
benderaglob.GLOBSTAR
benderanyaSetelah datang ke sini untuk meminta bantuan, saya membuat solusi sendiri dan ingin membagikannya. Ini didasarkan pada jawaban user2363986, tapi menurut saya ini lebih terukur. Artinya, jika Anda memiliki 1000 ekstensi, kodenya akan tetap terlihat elegan.
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
sumber
directoryPath = "/Users/bla/bla/images_dir*."
Berikut adalah varian pemahaman daftar satu baris dari jawaban Pat (yang juga termasuk yang Anda ingin gabungkan dalam direktori proyek tertentu):
import os, glob exts = ['*.txt', '*.mdown', '*.markdown'] files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))]
Anda mengulang ekstensi (
for ext in exts
), dan kemudian untuk setiap ekstensi Anda mengambil setiap file yang cocok dengan pola glob (for f in glob.glob(os.path.join(project_dir, ext)
).Solusi ini singkat , dan tanpa loop-for yang tidak perlu, pemahaman daftar bersarang, atau fungsi untuk mengacaukan kode. Zen yang murni, ekspresif, dan pythonic .
Solusi ini memungkinkan Anda memiliki daftar kustom
exts
yang dapat diubah tanpa harus memperbarui kode Anda. (Ini selalu merupakan praktik yang baik!)Pemahaman daftar sama dengan yang digunakan dalam solusi Laurent (yang saya pilih). Tetapi saya berpendapat bahwa biasanya tidak perlu memfaktorkan satu baris ke fungsi terpisah, itulah sebabnya saya memberikan ini sebagai solusi alternatif.
Bonus:
Jika Anda tidak hanya perlu mencari satu direktori, tetapi juga semua sub-direktori, Anda dapat meneruskan
recursive=True
dan menggunakan simbol glob multi-direktori**
1 :files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)]
Ini akan memanggil
glob.glob('<project_dir>/**/*.txt', recursive=True)
dan seterusnya untuk setiap ekstensi.1 Secara teknis,
**
simbol bola hanya cocok dengan satu atau lebih karakter termasuk garis miring/
(tidak seperti simbol bola tunggal*
). Dalam praktiknya, Anda hanya perlu mengingat bahwa selama Anda mengapit**
garis miring ke depan (pemisah jalur), itu cocok dengan nol atau lebih direktori.sumber
files = glob.glob('*.txt') files.extend(glob.glob('*.dat'))
sumber
Saya telah merilis Formic yang mengimplementasikan beberapa penyertaan dengan cara yang mirip dengan FileSet dan Globs Apache Ant .
Pencarian dapat dilakukan:
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
Karena Ant glob lengkap diimplementasikan, Anda dapat menyertakan direktori yang berbeda dengan setiap pola, sehingga Anda hanya dapat memilih file .txt tersebut dalam satu subdirektori, dan .markdown di subdirektori lainnya, misalnya:
patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ]
Saya harap ini membantu.
sumber
Fungsi berikut berfungsi
_glob
untuk beberapa ekstensi file.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")
sumber
Ini adalah solusi 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("~"))
Juga mengabaikan semua nama file yang dimulai dengan
~
.sumber
Tidak
glob
, tapi inilah cara lain menggunakan pemahaman daftar:extensions = 'txt mdown markdown'.split() projectFiles = [f for f in os.listdir(projectDir) if os.path.splitext(f)[1][1:] in extensions]
sumber
Anda dapat mencoba membuat daftar manual yang membandingkan ekstensi yang ada dengan yang Anda butuhkan.
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)
sumber
import os import glob import operator from functools import reduce types = ('*.jpg', '*.png', '*.jpeg') lazy_paths = (glob.glob(os.path.join('my_path', t)) for t in types) paths = reduce(operator.add, lazy_paths, [])
https://docs.python.org/3.5/library/functools.html#functools.reduce https://docs.python.org/3.5/library/operator.html#operator.add
sumber
Untuk
glob
beberapa jenis file, Anda perlu memanggilglob()
fungsi beberapa kali dalam satu putaran. Karena fungsi ini mengembalikan daftar, Anda perlu menggabungkan daftar.Misalnya, fungsi ini melakukan pekerjaan:
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))]
Penggunaan sederhana:
project_dir = "path/to/project/dir" for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')): print(path)
Anda juga dapat menggunakan
glob.iglob()
untuk memiliki iterator:def iglob_filetypes(root_dir, *patterns): return (path for pattern in patterns for path in glob.iglob(os.path.join(root_dir, pattern)))
sumber
Gunakan daftar ekstensi dan lakukan iterasi
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)
sumber
Anda bisa menggunakan filter:
import os import glob projectFiles = filter( lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] glob.glob(os.path.join(projectDir, "*")) )
sumber
Anda juga bisa menggunakan
reduce()
seperti ini:import glob file_types = ['*.txt', '*.mdown', '*.markdown'] project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types))
ini membuat daftar dari
glob.glob()
untuk setiap pola dan menguranginya menjadi satu daftar.sumber
Satu glob, banyak ekstensi ... tetapi solusi yang tidak sempurna (mungkin cocok dengan file lain).
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)
sumber
Saya memiliki masalah yang sama dan inilah yang saya temukan
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))
sumber
Namun solusi lain (gunakan
glob
untuk mendapatkan jalur menggunakan banyak kecocokanpatterns
dan gabungkan semua jalur menjadi satu daftar menggunakanreduce
danadd
):import functools, glob, operator paths = functools.reduce(operator.add, [glob.glob(pattern) for pattern in [ "path1/*.ext1", "path2/*.ext2"]])
sumber
Jika Anda menggunakan
pathlib
coba ini:import pathlib extensions = ['.py', '.txt'] root_dir = './test/' files = filter(lambda p: p.suffix in extensions, pathlib.Path(root_dir).glob('**/*')) print(list(files))
sumber
Dari hasil yang saya peroleh dari uji empiris, ternyata itu
glob.glob
bukan cara yang lebih baik untuk menyaring file dengan ekstensinya. Beberapa alasannya adalah:Saya telah menguji (untuk kebenaran dan efisiensi waktu)
4
berbagai metode berikut untuk memfilter file berdasarkan ekstensi dan menempatkannya dilist
: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
Dengan menjalankan kode di atas di laptop saya, saya memperoleh hasil auto-explicative berikut.
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.
Cara tercepat untuk memfilter file berdasarkan ekstensi, bahkan bisa menjadi yang paling jelek. Yaitu,
for
loop bersarang danstring
perbandingan menggunakanendswith()
metode.Selain itu, seperti yang Anda lihat, algoritme globbing (dengan pola
E:\x\y\z\**/*[py][pyc]
) bahkan dengan2
ekstensi yang diberikan (py
danpyc
) juga mengembalikan hasil yang salah.sumber
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)
sumber
Dari jawaban sebelumnya
glob('*.jpg') + glob('*.png')
Ini yang lebih pendek,
from glob import glob extensions = ['jpg', 'png'] # to find these filename extensions # Method 1: loop one by one and extend to the output list output = [] [output.extend(glob(f'*.{name}')) for name in extensions] print(output) # Method 2: even shorter # loop filename extension to glob() it and flatten it to a list output = [p for p2 in [glob(f'*.{name}') for name in extensions] for p in p2] print(output)
sumber
Ini Seharusnya Berhasil:
import glob extensions = ('*.txt', '*.mdown', '*.markdown') for i in extensions: for files in glob.glob(i): print (files)
sumber