在Python中比较两个路径

46

请考虑:

path1 = "c:/fold1/fold2"
list_of_paths = ["c:\\fold1\\fold2","c:\\temp\\temp123"]

if path1 in list_of_paths:
    print "found"

我希望if语句返回True,但它评估为False,因为它是一个字符串比较。

如何比较两个路径,不考虑它们具有前斜杠或后斜杠?我不想使用replace函数将两个字符串转换为通用格式。

7个回答

47

使用os.path.normpathc:/fold1/fold2转换为c:\fold1\fold2

>>> path1 = "c:/fold1/fold2"
>>> list_of_paths = ["c:\\fold1\\fold2","c:\\temp\\temp123"]
>>> os.path.normpath(path1)
'c:\\fold1\\fold2'
>>> os.path.normpath(path1) in list_of_paths
True
>>> os.path.normpath(path1) in (os.path.normpath(p) for p in list_of_paths)
True
  • os.path.normpath(path1) in map(os.path.normpath, list_of_paths) 也可以工作,但它会构建一个包含整个路径项的列表,即使在中间有匹配项。(在Python 2.x 中)

在Windows上,您必须使用os.path.normcase来比较路径,因为在Windows上,路径不区分大小写。


11
在Windows上进行比较时,应该是不区分大小写的,因此请添加os.path.normcase以将其转换为小写。 - ondra
但是原帖作者说这些斜杠可能出现在任何位置。 - Aswin Murugesh
@JagannathKs,稍作修改(lis3 -> list3x\y -> x\\yx\y\z -> x\\y\\z)并创建目录a\b\cx\y\z后,它对我有效(打印“found”)。 - falsetru
2
在Windows上仍然有一个陷阱:由于8.3文件名的愚蠢,'c:\users\administrator\foo.txt'和'c:\users\admini~1\foo.txt'是同一个文件。 - cbare
3
我认为你想使用os.path.realpath,以覆盖像@cbare提到的情况。 - Jonathon Reinhart
显示剩余3条评论

24

所有这些答案都提到了os.path.normpath,但没有一个提到了os.path.realpath

os.path.realpath(path)

返回指定文件名的规范化绝对路径,消除路径中遇到的任何符号链接(如果操作系统支持)。

自版本2.2起新增。

那么:

if os.path.realpath(path1) in (os.path.realpath(p) for p in list_of_paths):
    # ...

你能解释一下为什么这比normpath更可取吗?唯一的区别是符号链接吗? - Ben Jones
1
我相信那是唯一的区别。 - Jonathon Reinhart

20

os.path 模块包含多个函数,用于规范化文件路径,以便等效路径归一化为相同的字符串。你可能需要使用 normpathnormcaseabspathsamefile 或其他工具。


5
使用 os.path.samefile(path1, path2) 命令可以避免在执行字符串比较之前使用 normpath()realpath() 或者(在 Windows 操作系统上)normcase()。但是,需要确保两个路径都存在于文件系统中,否则会引发 FileNotFoundError 异常。此外,该命令不能解析主目录相对路径,例如 ~/Path/To/File,如果需要解析这种路径,请使用 expanduser()。请注意:Python 3.2 版本已经为 Windows 操作系统添加了 samefile() 支持。 - mattst
+1同样适用于samefile,顺便提一下:尽管名为“samefile”,但也可以用于检查目录!请参见https://docs.python.org/3/library/os.path.html - Stefan

9
如果您正在使用,您可以使用来实现您的目标:
import pathlib
path1 = pathlib.Path("c:/fold1/fold2")
list_of_paths = [pathlib.Path(path) for path in ["c:\\fold1\\fold2","c:\\temp\\temp123"]]
assert path1 in list_of_paths

我喜欢这个答案,但我想补充一下,您还可以使用相对路径,如下所示: Path('..').resolve() in [Path('.').resolve().parent],这通常是 True,除非没有更多的父级。 - notfancy

2

将list_of_paths存储为列表而不是字符串:

list_of_paths = [["c:","fold1","fold2"],["c","temp","temp123"]]

然后,通过“/”或“\”(无论哪个存在)来拆分给定路径,然后使用in关键字。


嗨,Ashwin,我不确定哪个变量具有哪个斜杠,因为它们都是动态生成的,而且我不能替换每个字符串,因为我将浏览大量数据。 - Jagannath Ks

2

在比较路径之前,请使用os.path.normpath来规范化路径。例如:

if any(os.path.normpath(path1) == os.path.normpath(p)
       for p in list_of_paths):
    print "found"

os.path.normpath 用于规范化路径,我们应该使用 os.path.realpath 来获取真实路径。 - baky
@baky 这取决于确切的要求。由于 OP 请求比较“无论是正斜杠还是反斜杠”,而 normpath 满足此要求。当然,OP 两年半前可能错误陈述了他们的要求,但那只是猜测。 - user4815162342

0

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