忽略Linux上的glob()中的大小写

时间:2011-11-16 11:59:04

标签: python linux

我正在编写一个脚本,该脚本必须处理由Windows和Linux用户手动修改的目录。 Windows用户往往不关心分配文件名的情况。

有没有办法在Python的Linux端处理这个问题,即我可以获得不区分大小写的类似行星的行为吗?

8 个答案:

答案 0 :(得分:42)

您可以使用[cC]通过

替换每个字母c
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)))

答案 1 :(得分:22)

使用不区分大小写的正则表达式而不是glob模式。 fnmatch.translate从glob模式生成一个正则表达式,所以

re.compile(fnmatch.translate(pattern), re.IGNORECASE)

给出了一个不区分大小写的glob模式作为编译的RE。

请记住,如果文件系统由类Unix文件系统上的Linux机箱托管,用户将能够在文件系统中创建文件fooFooFOO同一目录。

答案 2 :(得分:6)

非递归

为了检索目录“path”的文件(和仅文件),使用“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)]

递归

with walk:

result = []
for root, dirs, files in os.walk(path, topdown=True):
  result += [os.path.join(root, j) for j in files \
             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)]

答案 3 :(得分:2)

这是我对Python的非递归文件搜索,具有类似于Python 3.5+的行为

# 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 \
            else re.compile(fnmatch.translate(glob_pat))
    return [n for n in os.listdir(os.path.expanduser(path)) if rule.match(n)]

注意:此版本处理home directory expansion

答案 4 :(得分:1)

根据您的情况,您可以对文件模式和文件夹列表中的结果使用.lower(),然后仅将模式与文件名进行比较

答案 5 :(得分:0)

从@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 \
            else re.compile(fnmatch.translate(glob_pat))
    return [n for n in glob.glob(os.path.join(path, '*')) if rule.match(n)]

答案 6 :(得分:0)

这是一个使用 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)

答案 7 :(得分:0)

我只是想要一个这样的变体,如果我指定文件扩展名,我只对大小写不敏感——例如,我希望“.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 和 { {1}} 但不是 FOO.JPGfoo.JPG;如果您的路径是病态的,您还有其他问题)