我在目录bar
中有一个目录foo
,目录foo_file.txt
中有文件foo
,目录bar_file.txt
中有文件bar
;即。
computer$ ls
foo/
computer$ ls foo/
bar/ foo_file.txt
computer$ ls foo/bar/
bar_file.txt
使用python os.path.relpath函数,我希望:
os.path.relpath('foo/bar/bar_file.txt', 'foo/foo_file.txt')
给我:
'bar/bar_file.txt'
然而,它实际上给了我:
'../bar/bar_file.txt'
这是为什么?有没有一种简单的方法来获得我想要的行为?
编辑:这是在Linux上使用Python 2.7.3
答案 0 :(得分:7)
os.path.relpath()
假设其参数是目录。
>>> os.path.join(os.path.relpath(os.path.dirname('foo/bar/bar_file.txt'),
os.path.dirname('foo/foo_file.txt')),
os.path.basename('foo/bar/bar_file.txt'))
'bar/bar_file.txt'
答案 1 :(得分:5)
[]
将从arg1的目录中给出arg2的相对路径。为了在你的情况下从arg2到arg1,你需要cd一个目录(..),去吧目录(bar),然后是bar_file.txt。因此,相对路径是
os.path.relpath(arg1, arg2)
答案 2 :(得分:0)
relpath
的行为异常。它将路径的所有元素视为目录。因此,在路径中:
/path/to/a/file.txt
file.txt
也被视为目录。
这意味着当您在两条路径上运行relpath
时,
>>> from os.path import relpath
>>> relpath('/path/to/dest/file.txt', '/path/to/origin/file.txt')
'../../dest/file.txt'
这是不正确的。从目录源到目标的真实相对路径为'../dest/file.txt'
如果您尝试创建符号链接,但最终导致它们的格式错误,这会特别令人沮丧。
要解决此问题,我们必须首先找出路径是否指向文件,否则,我们可以照常进行比较,否则我们需要从头删除文件名,仅对目录进行比较,然后然后将文件添加回末尾。
请注意,这仅在您实际在系统上创建了这些文件时才有效,python必须访问文件系统以查找节点类型。
import os
def realrelpath(origin, dest):
'''Get the relative path between two paths, accounting for filepaths'''
# get the absolute paths so that strings can be compared
origin = os.path.abspath(origin)
dest = os.path.abspath(dest)
# find out if the origin and destination are filepaths
origin_isfile = os.path.isfile(origin)
dest_isfile = os.path.isfile(dest)
# if dealing with filepaths,
if origin_isfile or dest_isfile:
# get the base filename
filename = os.path.basename(origin) if origin_isfile else os.path.basename(dest)
# in cases where we're dealing with a file, use only the directory name
origin = os.path.dirname(origin) if origin_isfile else origin
dest = os.path.dirname(dest) if dest_isfile else dest
# get the relative path between directories, then re-add the filename
return os.path.join(os.path.relpath(dest, origin), filename)
else:
# if not dealing with any filepaths, just run relpath as usual
return os.path.relpath(dest, origin)
要获取从目录源到目标的真实相对路径,请运行:
>>> relrealpath('/path/to/origin/file.txt', '/path/to/dest/file.txt')
'../dest/file.txt'
我翻转了参数顺序,因为在我的大脑中说“我想知道从arg1到arg2的相对路径”更有意义,标准的relpath
实现使它倒退(可能因为这就是UNIX的方式。)
需要访问文件系统是relpath
具有这种奇怪行为的真正原因。文件系统调用很昂贵,因此python让您知道是要处理文件还是目录,而只在提供的路径上执行字符串操作。
注意:可能有一种方法可以使realrelpath
函数更有效率。例如,我不确定是否需要abspath
调用,或者是否可以将它们与os.path.isfile
检查捆绑在一起并返回一个返回更多信息的syscall。我欢迎改进。