Python不区分大小写的文件名?

10

我需要根据文件名加载文件,但是我获取的文件名是不区分大小写的。例如"A.txt"实际上可能是"a.txt"。如何快速地解决这个问题(而不是生成所有可能的名称并尝试每个名称)?


不应该有影响,我得到的名称(大小写不敏感)是从脚本文件中解析出来的。 - user975135
1
操作系统(以及文件系统)在这里确实很重要。 - johnsyweb
抱歉,我的意思是1)我从脚本中获取文件名。2)我希望我的程序跨平台运行。因此,无论我使用什么操作系统都没有关系。 - user975135
4个回答

8
您可以列出文件所在的目录(os.listdir),然后查看是否有与您的文件名匹配的内容。可以通过将两个文件名转换为小写并进行比较来进行匹配。

是的,但它是否高效呢?考虑到文件夹可能有数千个文件? - user975135
6
在您尝试了这种方法并且速度不够快以满足您的需求之前,无需担心效率低下。 - dreamlax
我以前用 Python 一次性处理过成千上万个字符串,所以如果有其他方法的话,我认为不应该忽略它。 - user975135
@user975135:由于我们讨论的是磁盘读取,我相当确定这段Python代码的运行时开销将会很小,相对于操作系统查询硬盘和列出文件所花费的时间。 - Eli Bendersky

6

如果你想进行目录匹配并比较每个项目,就不能不获取目录列表和需要查找的项,然后将它们都转换为相同的大小写进行比较。文件系统区分大小写,这就是全部内容。

这里有一个函数(其实是两个),我编写了完整的代码,可以进行不区分大小写的文件名匹配,并且支持递归搜索:http://portableapps.hg.sourceforge.net/hgweb/portableapps/development-toolkit/file/775197d56e86/utils.py#l78

def path_insensitive(path):
    """
    Get a case-insensitive path for use on a case sensitive system.

    >>> path_insensitive('/Home')
    '/home'
    >>> path_insensitive('/Home/chris')
    '/home/chris'
    >>> path_insensitive('/HoME/CHris/')
    '/home/chris/'
    >>> path_insensitive('/home/CHRIS')
    '/home/chris'
    >>> path_insensitive('/Home/CHRIS/.gtk-bookmarks')
    '/home/chris/.gtk-bookmarks'
    >>> path_insensitive('/home/chris/.GTK-bookmarks')
    '/home/chris/.gtk-bookmarks'
    >>> path_insensitive('/HOME/Chris/.GTK-bookmarks')
    '/home/chris/.gtk-bookmarks'
    >>> path_insensitive("/HOME/Chris/I HOPE this doesn't exist")
    "/HOME/Chris/I HOPE this doesn't exist"
    """

    return _path_insensitive(path) or path


def _path_insensitive(path):
    """
    Recursive part of path_insensitive to do the work.
    """

    if path == '' or os.path.exists(path):
        return path

    base = os.path.basename(path)  # may be a directory or a file
    dirname = os.path.dirname(path)

    suffix = ''
    if not base:  # dir ends with a slash?
        if len(dirname) < len(path):
            suffix = path[:len(path) - len(dirname)]

        base = os.path.basename(dirname)
        dirname = os.path.dirname(dirname)

    if not os.path.exists(dirname):
        dirname = _path_insensitive(dirname)
        if not dirname:
            return

    # at this point, the directory exists but not the file

    try:  # we are expecting dirname to be a directory, but it could be a file
        files = os.listdir(dirname)
    except OSError:
        return

    baselow = base.lower()
    try:
        basefinal = next(fl for fl in files if fl.lower() == baselow)
    except StopIteration:
        return

    if basefinal:
        return os.path.join(dirname, basefinal) + suffix
    else:
        return

4
这是一个简单的递归函数,用于执行Eli建议的搜索操作:
def find_sensitive_path(dir, insensitive_path):

    insensitive_path = insensitive_path.strip(os.path.sep)

    parts = insensitive_path.split(os.path.sep)
    next_name = parts[0]
    for name in os.listdir(dir):
        if next_name.lower() == name.lower():
            improved_path = os.path.join(dir, name)
            if len(parts) == 1:
                return improved_path
            else:
                return find_sensitive_path(improved_path, os.path.sep.join(parts[1:]))
    return None

1
创建一个目录列表,并创建一个字典,其中包含大写文件名与其实际大小写文件名的映射。然后将输入转换为大写,并在字典中查找它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接