通过比较两个绝对路径获取相对路径 [英] Get relative path from comparing two absolute paths

查看:23
本文介绍了通过比较两个绝对路径获取相对路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比如说,我有两个绝对路径.我需要检查其中一个路径所指的位置是否是另一个路径的后代.如果为真,我需要从祖先那里找出后代的相对路径.在 Python 中实现它的好方法是什么?我可以从中受益的任何图书馆?

解决方案

os.path.commonprefix()os.path.relpath() 是你的朋友:

<预><代码>>>>打印 os.path.commonprefix(['/usr/var/log', '/usr/var/security'])'/usr/var'>>>print os.path.commonprefix(['/tmp', '/usr/var']) # 没有公共前缀:root 是公共前缀'/'

因此,您可以测试公共前缀是否为路径之一,即路径之一是否为共同祖先:

paths = [..., ..., ...]common_prefix = os.path.commonprefix(list_of_paths)如果路径中的 common_prefix:…

然后您可以找到相对路径:

relative_paths = [os.path.relpath(path, common_prefix) for path in path]

你甚至可以用这种方法处理两条以上的路径,并测试所有路径是否都在其中一条之下.

PS:根据路径的外观,您可能希望先执行一些规范化(这在不知道它们是否总是以/"结尾的情况下很有用,或者如果某些路径是相对的).相关函数包括 os.path.abspath()os.path.normpath().

PPS:正如 Peter Briggs 在评论中提到的,上面描述的简单方法可能会失败:

<预><代码>>>>os.path.commonprefix(['/usr/var', '/usr/var2/log'])'/usr/var'

即使 /usr/var 不是路径的公共前缀.在调用 commonprefix() 之前强制所有路径以/"结尾解决了这个(特定的)问题.

PPPS:正如 bluenote10 提到的,添加斜线并不能解决一般问题.这是他的后续问题:如何规避Python 的 os.path.commonprefix?

PPPPS:从 Python 3.4 开始,我们有 pathlib,一个提供更合理的路径操作环境的模块.我猜可以通过获取每个路径的所有前缀来获得一组路径的公共前缀(使用 PurePath.parents()),取所有这些父集的交集,并选择最长的公共前缀.

PPPPPS:Python 3.5 为这个问题引入了一个合适的解决方案:os.path.commonpath(),返回有效路径.

Say, I have two absolute paths. I need to check if the location referring to by one of the paths is a descendant of the other. If true, I need to find out the relative path of the descendant from the ancestor. What's a good way to implement this in Python? Any library that I can benefit from?

解决方案

os.path.commonprefix() and os.path.relpath() are your friends:

>>> print os.path.commonprefix(['/usr/var/log', '/usr/var/security'])
'/usr/var'
>>> print os.path.commonprefix(['/tmp', '/usr/var'])  # No common prefix: the root is the common prefix
'/'

You can thus test whether the common prefix is one of the paths, i.e. if one of the paths is a common ancestor:

paths = […, …, …]
common_prefix = os.path.commonprefix(list_of_paths)
if common_prefix in paths:
    …

You can then find the relative paths:

relative_paths = [os.path.relpath(path, common_prefix) for path in paths]

You can even handle more than two paths, with this method, and test whether all the paths are all below one of them.

PS: depending on how your paths look like, you might want to perform some normalization first (this is useful in situations where one does not know whether they always end with '/' or not, or if some of the paths are relative). Relevant functions include os.path.abspath() and os.path.normpath().

PPS: as Peter Briggs mentioned in the comments, the simple approach described above can fail:

>>> os.path.commonprefix(['/usr/var', '/usr/var2/log'])
'/usr/var'

even though /usr/var is not a common prefix of the paths. Forcing all paths to end with '/' before calling commonprefix() solves this (specific) problem.

PPPS: as bluenote10 mentioned, adding a slash does not solve the general problem. Here is his followup question: How to circumvent the fallacy of Python's os.path.commonprefix?

PPPPS: starting with Python 3.4, we have pathlib, a module that provides a saner path manipulation environment. I guess that the common prefix of a set of paths can be obtained by getting all the prefixes of each path (with PurePath.parents()), taking the intersection of all these parent sets, and selecting the longest common prefix.

PPPPPS: Python 3.5 introduced a proper solution to this question: os.path.commonpath(), which returns a valid path.

这篇关于通过比较两个绝对路径获取相对路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆