在 Linux 上,忽略 glob() 中的大小写
- 2024-11-12 08:36:00
- admin 原创
- 22
问题描述:
我正在编写一个脚本,该脚本必须适用于 Windows 和 Linux 用户手动修改的目录。Windows 用户在分配文件名时往往根本不关心大小写。
有没有办法在 Python 的 Linux 端处理这个问题,即我是否可以获得不区分大小写的类似 glob 的行为?
解决方案 1:
您可以将每个字母字符 c 替换为 [cC],方法是
import glob
def insensitive_glob(pattern):
def either(c):
return '[%s%s]' % (c.lower(), c.upper()) if c.isalpha() else c
return glob.glob(''.join(map(either, pattern)))
解决方案 2:
使用不区分大小写的正则表达式,而不是 glob 模式。fnmatch.translate
从 glob 模式生成正则表达式,因此
re.compile(fnmatch.translate(pattern), re.IGNORECASE)
为您提供一个不区分大小写的 glob 模式版本作为已编译的 RE。
请记住,如果文件系统由类 Unix 文件系统上的 Linux 机器托管,则用户将能够在同一目录中创建文件foo
、Foo
和。FOO
解决方案 3:
非递归
为了检索目录“路径”的文件(且仅文件),使用“globexpression”:
list_path = [i for i in os.listdir(path) if os.path.isfile(os.path.join(path, i))]
result = [os.path.join(path, j) for j in list_path if re.match(fnmatch.translate(globexpression), j, re.IGNORECASE)]
递归地
步行:
result = []
for root, dirs, files in os.walk(path, topdown=True):
result += [os.path.join(root, j) for j in files \n if re.match(fnmatch.translate(globexpression), j, re.IGNORECASE)]
最好也编译正则表达式,因此
re.match(fnmatch.translate(globexpression)
执行(循环之前):
reg_expr = re.compile(fnmatch.translate(globexpression), re.IGNORECASE)
然后在循环中替换:
result += [os.path.join(root, j) for j in files if re.match(reg_expr, j)]
解决方案 4:
起始价python-3.12,您可以使用将参数设置Path.glob(pattern, *, case_sensitive=None)
为的 APIcase_sensitive
`False`来获取所需的行为。
默认情况下,或者当
case_sensitive
仅关键字参数设置为 时
,此方法使用特定于平台的大小写规则匹配路径:通常,在POSIXNone
上区分大小写,在Windows上不区分大小写。设置为或可覆盖此行为。case_sensitive
`True`False
解决方案 5:
这是我针对 Python 3.5+ 的非递归文件搜索,具有类似 glob 的行为
# Eg: find_files('~/Downloads', '*.Xls', ignore_case=True)
def find_files(path: str, glob_pat: str, ignore_case: bool = False):
rule = re.compile(fnmatch.translate(glob_pat), re.IGNORECASE) if ignore_case \n else re.compile(fnmatch.translate(glob_pat))
return [n for n in os.listdir(os.path.expanduser(path)) if rule.match(n)]
注意:此版本处理主目录扩展
解决方案 6:
根据您的情况,您可能.lower()
同时使用文件模式和文件夹列表的结果,然后将模式与文件名进行比较
解决方案 7:
借鉴@Timothy C. Quinn 的回答,此修改允许在路径中的任何位置使用通配符。诚然,这仅对 glob_pat 参数不区分大小写。
import re
import os
import fnmatch
import glob
def find_files(path: str, glob_pat: str, ignore_case: bool = False):
rule = re.compile(fnmatch.translate(glob_pat), re.IGNORECASE) if ignore_case \n else re.compile(fnmatch.translate(glob_pat))
return [n for n in glob.glob(os.path.join(path, '*')) if rule.match(n)]
解决方案 8:
这是一个工作示例fnmatch.translate()
:
from glob import glob
from pathlib import Path
import fnmatch, re
mask_str = '"*_*_yyww.TXT" | "*_yyww.TXT" | "*_*_yyww_*.TXT" | "*_yyww_*.TXT"'
masks_list = ["yyyy", "yy", "mmmmm", "mmm", "mm", "#d", "#w", "#m", "ww"]
for mask_item in masks_list:
mask_str = mask_str.replace(mask_item, "*")
clean_quotes_and_spaces = mask_str.replace(" ", "").replace('"', '')
remove_double_star = clean_quotes_and_spaces.replace("**", "*")
masks = remove_double_star.split("|")
cwd = Path.cwd()
files = list(cwd.glob('*'))
print(files)
files_found = set()
for mask in masks:
mask = re.compile(fnmatch.translate(mask), re.IGNORECASE)
print(mask)
for file in files:
if mask.match(str(file)):
files_found.add(file)
print(files_found)
解决方案 9:
我只是想要一个变体,如果我指定文件扩展名,我只会不区分大小写 - 例如,我希望“.jpg”和“.JPG”被同样抓取。这是我的变体:
import re
import glob
import os
from fnmatch import translate as regexGlob
from platform import system as getOS
def linuxGlob(globPattern:str) -> frozenset:
"""
Glob with a case-insensitive file extension
"""
base = set(glob.glob(globPattern, recursive= True))
maybeExt = os.path.splitext(os.path.basename(globPattern))[1][1:]
caseChange = set()
# Now only try the extended insensitivity if we've got a file extension
if len(maybeExt) > 0 and getOS() != "Windows":
rule = re.compile(regexGlob(globPattern), re.IGNORECASE)
endIndex = globPattern.find("*")
if endIndex == -1:
endIndex = len(globPattern)
crawl = os.path.join(os.path.dirname(globPattern[:endIndex]), "**", "*")
checkSet = set(glob.glob(crawl, recursive= True)) - base
caseChange = set([x for x in checkSet if rule.match(x)])
return frozenset(base.union(caseChange))
我实际上并没有将不敏感性限制在扩展上,因为我很懒,但是混淆空间非常小(例如,你想捕获FOO.jpg
和FOO.JPG
但不想捕获 foo.JPG
或foo.jpg
;如果你的路径是病态的,你就会遇到其他问题)
解决方案 10:
def insensitive_glob(pattern):
def either(c):
return '[%s%s]' % (c.lower(), c.upper()) if c.isalpha() else c
return glob.glob(''.join(map(either, pattern)))
也可以是:
def insensitive_glob(pattern):
return glob.glob(
''.join([
'[' + c.lower() + c.upper() + ']'
if c.isalpha() else c
for c in pattern
])
)
解决方案 11:
使用名称文件递归搜索来改变您的答案:
def insensitive_for_glob(string_file):
return ''.join(['[' + c.lower() + c.upper() + ']' if c.isalpha() else c for c in string_file])
在代码的其他地方:
namefile = self.insensitive_for_glob(namefile)
lst_found_file = glob.glob(f'{file_path}/**/*{namefile}', recursive=True)
解决方案 12:
您可以简单地搜索大写和小写,然后添加结果,如下所示:
from pathlib import Path folder = Path('some_folder')
file_filter = '.txt'
files_in_folder = [files for files in (
list(folder.glob(f'*{file_filter.lower()}'))+
list(folder.glob(f'*{file_filter.upper()}'))
)]
这将找到以.txt
和.TXT
结尾的文件。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件