全球排除模式全球排除模式

我有一个目录,里面有一大堆文件: eee2314asd3442... ... 和 eph

我想排除所有以 eph开头的带有 glob函数的文件。

我该怎么做?

187657 次浏览

不能用 glob函数排除模式,globs 只允许 包容模式。球状语法是非常有限的(甚至一个 [!..]字符类 必须的匹配一个字符,所以它是一个 包含模式的每个字符不在类)。

你必须自己过滤,这里的列表内涵通常很好用:

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

您可以扣除集合并将其转换为列表:

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

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

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

虽然比较晚,但是你也可以选择将 python filter应用到 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']

正如已被接受的答案所提到的,您不能排除使用 globb 的模式,因此下面是一个过滤 globb 结果的方法。

接受的答案可能是最好的 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*"))

(在我的例子中,我有一些图像帧,偏置帧和平面帧都在一个目录中,我只需要图像帧)

Globb 的模式规则不是正则表达式。相反,它们遵循标准的 Unix 路径展开规则。只有几个特殊的字符: 两个不同的通配符,并且字符范围受[从 Pymotw: glob- 文件名模式匹配]支持。

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

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

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开头的所有文件。

在迭代文件夹中的所有文件时跳过特定文件如何! 下面的代码将跳过所有以“ 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)

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

如果字符 不是的位置很重要,例如用 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)

假设您有这样的目录结构:

.
├── asd3442
├── eee2314
├── eph334
├── eph_dir
│   ├── asd330
│   ├── eph_file2
│   ├── exy123
│   └── file_with_eph
├── eph_file
├── not_eph_dir
│   ├── ephXXX
│   └── with_eph
└── not_eph_rest

您可以使用 full globs 用 Pathlib和顶级目录的生成器过滤完整路径结果:

i_want=(fn for fn in Path(path_to).glob('*') if not fn.match('**/*/eph*'))


>>> list(i_want)
[PosixPath('/tmp/test/eee2314'), PosixPath('/tmp/test/asd3442'), PosixPath('/tmp/test/not_eph_rest'), PosixPath('/tmp/test/not_eph_dir')]

Pathlib 方法 火柴使用 globs 来匹配路径对象; globb '**/*/eph*'是任何通向名称以 'eph'开头的文件的完整路径。

或者,可以对 name.startswith('eph')使用 .name属性:

i_want=(fn for fn in Path(path_to).glob('*') if not fn.name.startswith('eph'))

如果只需要文件,不需要目录:

i_want=(fn for fn in Path(path_to).glob('*') if fn.is_file() and not fn.match('**/*/eph*'))
# [PosixPath('/tmp/test/eee2314'), PosixPath('/tmp/test/asd3442'), PosixPath('/tmp/test/not_eph_rest')]
 

同样的方法也适用于递归全局变量:

i_want=(fn for fn in Path(path_to).glob('**/*')
if fn.is_file() and not fn.match('**/*/eph*'))


# [PosixPath('/tmp/test/eee2314'), PosixPath('/tmp/test/asd3442'),
PosixPath('/tmp/test/not_eph_rest'), PosixPath('/tmp/test/eph_dir/asd330'),
PosixPath('/tmp/test/eph_dir/file_with_eph'), PosixPath('/tmp/test/eph_dir/exy123'),
PosixPath('/tmp/test/not_eph_dir/with_eph')]

要排除确切的单词,可能需要实现 自定义正则表达式指令,然后在 glob处理之前用空字符串替换它。

#!/usr/bin/env python3
import glob
import re


# glob (or fnmatch) does not support exact word matching. This is custom directive to overcome this issue
glob_exact_match_regex = r"\[\^.*\]"
path = "[^exclude.py]*py"  # [^...] is a custom directive, that excludes exact match


# Process custom directive
try:  # Try to parse exact match direction
exact_match = re.findall(glob_exact_match_regex, path)[0].replace('[^', '').replace(']', '')
except IndexError:
exact_match = None
else:  # Remove custom directive
path = re.sub(glob_exact_match_regex, "", path)
paths = glob.glob(path)
# Implement custom directive
if exact_match is not None:  # Exclude all paths with specified string
paths = [p for p in paths if exact_match not in p]


print(paths)

import glob
import re

“这是一条应该被排除在外的道路”
EXCLUDE = "/home/koosha/Documents/Excel"

files = glob.glob("/home/koosha/Documents/**/*.*" , recursive=True)
for file in files:
if re.search(EXCLUDE,file):
pass
else:
print(file)