2011-03-18 12 views
26

dosyaları filtrelemek için? Bu özel durumda * .png, * .gif, * .jpg veya * .jpeg ile biten tüm dosyaları almak istiyorum. ŞimdilikKullanım fnmatch.filter piton aşağıdaki kod parçası göz önüne alındığında birden fazla olası dosya uzantısı

Ben

for root, dirs, files in os.walk(directory): 
    for extension in ['jpg', 'jpeg', 'gif', 'png']: 
     for filename in fnmatch.filter(files, '*.' + extension): 
      pass 

ile geldi Ama çok şık ve ölçülebilir olmadığını düşünüyorum.

Birisi daha iyi bir fikre sahip midir?

+0

iyi olmalı flles hariç, ama 'tuple' burada (kusur arama!)' ('Jpg', 'jpeg', 'gif', 'png') 'daha iyi olurdu. – user225312

+4

@A A: Bu durumda neden bir tuple daha iyi? – tyrondis

cevap

35

: Eğer sadece bir kez her dosya adına dokunun istiyorsanız, kendi filtreleme işlevi tanımlayın?

for root, dirs, files in os.walk(directory): 
    for filename in files: 
     if filename.endswith(('.jpg', '.jpeg', '.gif', '.png')): 
      pass 
+0

teşekkürler - bu oldukça açık bir çözüm oldu - ama ben onu görmedim =) – tyrondis

+4

Bu yöntemin büyük/küçük harf duyarlı olduğunu unutmayın, örneğin 'annoying.GIF. Yukarıdaki örnekte yer almayacaktır. Bu, dosya adının normalleştirilmesiyle çözülebilir: '... eğer filename.lower() .sonwith (('. Jpg', '.jpeg', '.gif', '.png')) ...' – asherbar

3

Bu da gerçekten zarif değil, ama çalışır: Eğer arka arkaya + arama ve list yerine tuple kullanmıyorsanız belki de

for root, dirs, files in os.walk(directory): 
    for filename in fnmatch.filter(files, '*.png') + fnmatch.filter(files, '*.jpg') + fnmatch.filter(files, '*.jpeg') + fnmatch.filter(files, '*.gif'): 
     pass 
3

Bu, daha iyi bir yol olurdu. Eğer oluşturduktan sonra uzantısını değiştirmek için gidiş değildir çünkü

for root, dirs, files in os.walk(directory): 
    for extension in ('*.jpg', '*.jpeg', '*.gif', '*.png'): 
     for filename in fnmatch.filter(files, extension): 
      pass 

A tuple iyidir. Sadece bunları tekrarlamak için kullanıyorsun.

8

Kodunuzun gerçekten iyi olduğunu düşünüyorum. Yalnızca uzantıları (yani başka joker), neden sadece temel dize işlemlerini kullanmayan kontrol etmek gerekirse

def is_image_file(filename, extensions=['.jpg', '.jpeg', '.gif', '.png']): 
    return any(filename.endswith(e) for e in extensions) 

for root, dirs, files in os.walk(directory): 
    for filename in filter(is_image_file, files): 
     pass 
+0

Bunun bir fark yaratacağına emin misin? Neden bir tuple tanımlamıyorsunuz (sadece bir kere oluşturulacak, değil mi?) Ve bunlarla uğraşmıyorsunuz? (Sadece soruyorsun!) – user225312

+0

@AA: Kodunuzda, tuple, dış döngünün her yinelemesinde oluşturulacaktır. Kodumda, liste sadece bir kez oluşturulacak. Performans farkının burada alakalı olduğunu sanmıyorum. Benim önerim kod okunabilirliği hakkında daha fazla - senin de iyi. –

+0

Aah gerçekten. Sadece emin olmak istedim. – user225312

6

Bunu çok başarılı bir şekilde kullanıyorum.

import fnmatch 
import functools 
import itertools 
import os 

# Remove the annotations if you're not on Python3 
def find_files(dir_path: str=None, patterns: [str]=None) -> [str]: 
    """ 
    Returns a generator yielding files matching the given patterns 
    :type dir_path: str 
    :type patterns: [str] 
    :rtype : [str] 
    :param dir_path: Directory to search for files/directories under. Defaults to current dir. 
    :param patterns: Patterns of files to search for. Defaults to ["*"]. Example: ["*.json", "*.xml"] 
    """ 
    path = dir_path or "." 
    path_patterns = patterns or ["*"] 

    for root_dir, dir_names, file_names in os.walk(path): 
     filter_partial = functools.partial(fnmatch.filter, file_names) 

     for file_name in itertools.chain(*map(filter_partial, path_patterns)): 
      yield os.path.join(root_dir, file_name) 

Örnekler:

for f in find_files(test_directory): 
    print(f) 

verim: birden fazla modele sahip

.\test.json 
.\test.xml 
.\test.ini 
.\test_helpers.py 
.\__init__.py 

Test:

for f in find_files(test_directory, ["*.xml", "*.json", "*.ini"]): 
    print(f) 

verim:

.\test.json 
.\test.xml 
.\test.ini 
0

Dosyaları apache log dizinlerinde filtrelemek için kullanıyorum. Burada hataları

rep_filters = [now.strftime("%Y%m%d")] 
def files_filter(liste_fic, filters = rep_filters): 
    s = "(fic for fic in liste_fic if fic.find('error') < 0" 
    for filter in filters: 
     s += " and fic.find('%s') >=0 " % filter 
    s += ")" 
    return eval(s) 
İlgili konular