glob dışlama kalıbı


105

İçeriye dosyaların bir grup ile bir dizin var: eee2314, asd3442... ve eph.

Ben ile başlayan tüm dosyaları dışlamak istediğiniz ephile globfonksiyonu.

Nasıl yapabilirim?

Yanıtlar:


149

Glob için kalıp kuralları normal ifadeler değildir. Bunun yerine, standart Unix yol genişletme kurallarını izlerler. Yalnızca birkaç özel karakter vardır: iki farklı joker karakter ve karakter aralıkları [ glob'dan ] desteklenir .

Böylece bazı dosyaları kalıplarla dışarıda bırakabilirsiniz.
Örneğin, manifest dosyalarını (ile başlayan dosyalar _) glob ile hariç tutmak için şunları kullanabilirsiniz:

files = glob.glob('files_path/[!_]*')

10
Bu resmi belgelerde olmalıdır, lütfen birisi bunu docs.python.org/3.5/library/glob.html#glob.glob'a
Vitaly Zdanevich

6
Glob modellerinin, OP tarafından belirlenen gereksinimi doğrudan yerine getiremeyeceğini unutmayın: yalnızca ile başlayan ephancak başka herhangi bir şeyle başlayabilen dosyaları hariç tutma . örneğin [!e][!p][!h]ile başlayan dosyaları filtreleyecektir eee.
Martijn Pieters

60

Setleri düşebilirsiniz:

set(glob("*")) - set(glob("eph*"))

3
Gerçekten ilginç çözüm! Ama benim durumum, iki kez okuma yapmak için son derece yavaş olacak. Ayrıca, bir ağ dizininde bir klasörün içeriği büyükse, yine yavaş olacaktır. Ama her durumda, gerçekten kullanışlı.
Anastasios Andronidis

İşletim sisteminiz dosya sistemi isteklerini önbelleğe almalı, o kadar da kötü değil :)
neutrinus

Bunu kendim denedim, yeni TypeError'ı aldım: -: 'list' ve 'list' için desteklenmeyen işlenen türleri
Tom Busby

1
@TomBusby Bunları setlere dönüştürmeyi deneyin: set(glob("*")) - set(glob("eph*")) (ve "
eph

2
Tıpkı bir yan not gibi, glob listeleri döndürür, kümeleri değil, ancak bu tür bir işlem yalnızca kümeler üzerinde çalışır, dolayısıyla nötrinus onu neden kullandı . Bir liste olarak kalmasına ihtiyacınız varsa, tüm operasyonu bir kadroya sarın:list(set(glob("*")) - set(glob("eph")))
Nathan Smith

48

globİşlevle kalıpları hariç tutamazsınız , globlar yalnızca dahil etme kalıplarına izin verir . Sözdizimi globbing çok sınırlıdır (hatta bir [!..]karakter sınıfı gerekir bir nedenle, bir karakteri eşleştirmek içerme desen sınıfta değil her karakter için).

Kendi filtrelemenizi yapmanız gerekecek; burada bir liste anlayışı genellikle işe yarar:

files = [fn for fn in glob('somepath/*.txt') 
         if not os.path.basename(fn).startswith('eph')]

3
iglobListenin tamamını bellekte saklamaktan kaçınmak için burayı kullanın
Eugene Pankov

3
@Hardex: dahili olarak, yine deiglob listeler üretir ; tek yapmanız gereken filtreyi tembelce değerlendirmek. Bellek ayak izini azaltmaya yardımcı olmaz.
Martijn Pieters

@Hardex: Dizin adında bir glob kullanırsanız, bir puanınız olur, o zaman yinelediğinizde en fazla bir os.listdir()sonuç bellekte tutulur. Ancak somepath/*.txtbellekteki bir dizindeki tüm dosya adlarını okumalı, sonra bu listeyi yalnızca eşleşenlere indirgemelidir.
Martijn Pieters

haklısın, o kadar önemli değil, ama stokta CPython glob.glob(x) = list(glob.iglob(x)),. Fazla bir yük değil ama yine de bilmek güzel.
Eugene Pankov

Bu iki kez yinelenmiyor mu? Listeyi almak için dosyalara bir kez, ikincisi de listenin içinden? Eğer öyleyse, bunu tek seferde yapmak mümkün değil mi?
Ridhuvarshan

6

Oyuna geç kaldınız, ancak alternatif filterolarak aşağıdaki sonuca bir python uygulayabilirsiniz glob:

files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)

veya lambda'yı uygun bir normal ifade aramasıyla vb. değiştirmek ...

DÜZENLEME: Tam yolları kullanıyorsanız startswithbunun işe yaramayacağını anladım , bu nedenle bir normal ifadeye ihtiyacınız olacak

In [10]: a
Out[10]: ['/some/path/foo', 'some/path/bar', 'some/path/eph_thing']

In [11]: filter(lambda x: not re.search('/eph', x), a)
Out[11]: ['/some/path/foo', 'some/path/bar']

5

Klasördeki tüm dosyaları yinelerken belirli bir dosyayı atlamaya ne dersiniz! Aşağıdaki kod, 'eph' ile başlayan tüm excel dosyalarını atlar

import glob
import re
for file in glob.glob('*.xlsx'):
    if re.match('eph.*\.xlsx',file):
        continue
    else:
        #do your stuff here
        print(file)

Bu şekilde, bir klasöre belirli bir dosya kümesini dahil etmek / hariç tutmak için daha karmaşık normal ifade kalıplarını kullanabilirsiniz.


5

Karşılaştırın glob, tavsiye ederim pathlib, bir kalıbı filtrelemek çok basittir.

from pathlib import Path

p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]

ve daha karmaşık deseni filtrelemek istiyorsanız, bunu yapmak için bir işlev tanımlayabilirsiniz, örneğin:

def not_in_pattern(x):
    return (not x.name.startswith("eph")) and not x.name.startswith("epi")


filtered = [x for x in p.glob("**/*") if not_in_pattern(x)]

bu kodu kullanın, ile başlayan ephveya başlayan tüm dosyaları filtreleyebilirsiniz epi.


4

Daha genel olarak, bazı kabuk regexp'lerine uymayan dosyaları dışlamak için modülü kullanabilirsiniz fnmatch:

import fnmatch

file_list = glob('somepath')    
for ind, ii in enumerate(file_list):
    if not fnmatch.fnmatch(ii, 'bash_regexp_with_exclude'):
        file_list.pop(ind)

Yukarıdakiler önce belirli bir yoldan bir liste oluşturacak ve ardından normal ifadeyi istenen kısıtlamayla karşılamayan dosyaları açacaktır.


0

Kabul edilen yanıtta belirtildiği gibi, glob ile kalıpları hariç tutamazsınız, bu nedenle aşağıdaki glob sonucunuzu filtrelemek için bir yöntemdir.

Kabul edilen cevap muhtemelen bir şeyler yapmanın en iyi pitonik yoludur, ancak liste anlamalarının biraz çirkin göründüğünü düşünüyorsanız ve kodunuzu yine de en üst düzeyde numpythonic yapmak istiyorsanız (benim yaptığım gibi), o zaman bunu yapabilirsiniz (ancak bunun muhtemelen daha az verimli olduğunu unutmayın. liste anlama yönteminden daha fazla):

import glob

data_files = glob.glob("path_to_files/*.fits")

light_files = np.setdiff1d( data_files, glob.glob("*BIAS*"))
light_files = np.setdiff1d(light_files, glob.glob("*FLAT*"))

(Benim durumumda, hepsi tek bir dizinde bazı görüntü çerçeveleri, önyargı çerçeveleri ve düz çerçeveler vardı ve sadece görüntü çerçevelerini istedim)


0

Karakterin konumu önemli değilse , örneğin manifesto dosyalarını (nerede bulunursa bulunsun _) globve re- normal ifade işlemleriyle hariç tutmak için , şunları kullanabilirsiniz:

import glob
import re
for file in glob.glob('*.txt'):
    if re.match(r'.*\_.*', file):
        continue
    else:
        print(file)

Veya daha zarif bir şekilde - list comprehension

filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]

for mach in filtered:
    print(mach)

-1

Aşağıdaki yöntemi kullanabilirsiniz:

# Get all the files
allFiles = glob.glob("*")
# Files starting with eph
ephFiles = glob.glob("eph*")
# Files which doesnt start with eph
noephFiles = []
for file in allFiles:
    if file not in ephFiles:
        noephFiles.append(file)
# noepchFiles has all the file which doesnt start with eph.

Thank you.  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.