全局排除模式


Answers:


146

glob的模式规则不是正则表达式。相反,它们遵循标准的Unix路径扩展规则。仅有几个特殊字符:支持两种不同的通配符,并且支持字符范围[from glob ]。

因此,您可以排除某些带有模式的文件。
例如,要排除清单文件(以开头的文件_)和glob,可以使用:

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

10
这必须在官方文档中,请有人将其添加到docs.python.org/3.5/library/glob.html#glob.glob
Vitaly Zdanevich 2016年

6
请注意,全局模式无法直接满足OP:提出的要求,仅排除以开头eph但可以以任何其他开头的文件。[!e][!p][!h]会过滤掉eee以例如开头的文件。
马丁·彼得

60

您可以扣除集合:

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

3
真的很有趣的解决方案!但是我的案子要读两次会非常慢。同样,如果文件夹的内容在网络目录上很大,又会变慢。但是无论如何,真的很方便。
Anastasios Andronidis 2014年

您的操作系统应该缓存文件系统请求,所以还不错:)
neutrinus 2014年

我自己试了一下,我刚好遇到TypeError:-:'list'和'list'不受支持的操作数类型
Tom Busby 2014年

1
@TomBusby尝试将它们转换为集合:(set(glob("*")) - set(glob("eph*")) 并注意*在“ eph *”的末尾)
Jaszczur 2014年

2
只是附带说明,glob返回列表而不返回集合,但是这种操作仅对集合有效,因此为什么neutrinus对其进行强制转换。如果您需要它来保留列表,只需将整个操作包装在演员表中:list(set(glob("*")) - set(glob("eph")))
Nathan Smith

48

您不能使用该glob功能排除模式,Glob仅允许包含模式。通配符语法非常有限(即使[!..]字符类也必须与字符匹配,所以它是一个对于不在类中的每个字符,包含模式)。

您必须自己进行过滤;列表理解通常在这里很有效:

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

3
使用iglob此处避免将完整列表存储在内存中
Eugene Pankov 2014年

3
@Hardex:在内部,仍然iglob产生列表;您要做的只是懒惰地评估过滤器。这无助于减少内存占用。
马丁·皮特斯

@Hardex:如果在目录名称中使用glob,那么您会有一个要点,然后在进行os.listdir()迭代时最多将一个结果保存在内存中。但是somepath/*.txt必须读取内存中一个目录中的所有文件名,然后将该列表缩小为仅匹配的文件名。
马丁·彼得斯

没错,这并不重要,但是有现货CPython glob.glob(x) = list(glob.iglob(x))。没有太多的开销,但还是很高兴知道。
尤金·潘科夫

这不是重复两次吗?一次通过文件获取列表,第二次通过列表本身?如果是这样,不可能一次迭代吗?
Ridhuvarshan

6

游戏晚了,但是您也可以将pythonfilter应用于结果glob

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

或将Lambda替换为适当的正则表达式搜索等。

编辑:我只是意识到,如果您使用完整路径startswith将无法正常工作,因此您需要一个正则表达式

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

如何在遍历文件夹中的所有文件时跳过特定文件!下面的代码将跳过所有以'eph'开头的Excel文件

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

这样,您可以使用更复杂的正则表达式模式在文件夹中包含/排除一组特定的文件。


5

glob,我建议比较一下,pathlib过滤一个模式很简单。

from pathlib import Path

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

如果要过滤更复杂的模式,可以定义一个函数来执行此操作,就像:

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)]

使用该代码,您可以过滤以eph或开头的所有文件epi


4

更一般而言,要排除不符合某些shell regexp的文件,可以使用module 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)

上面的代码将首先从给定的路径生成一个列表,然后弹出不满足正则表达式要求的约束的文件。


这应该是公认的答案。
菲利普·雷米

0

如公认的答案所述,您不能使用glob排除模式,因此以下是一种过滤glob结果的方法。

公认的答案可能是最好的pythonic做事方式,但是如果您认为列表理解看起来有些丑陋,并且无论如何都想使代码最大化numpythonic(就像我一样),那么您可以这样做(但是请注意,这可能效率较低)比列表理解方法):

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*"))

(以我为例,我在一个目录中有一些图像帧,偏置帧和平面帧,而我只想要这些图像帧)


0

如果字符的位置并不重要,那就是例如排除清单文件(无论它被发现_),与globre-正则表达式的操作,您可以使用:

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

或者以一种更优雅的方式- list comprehension

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

for mach in filtered:
    print(mach)

-1

您可以使用以下方法:

# 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.  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.