假设我有两条路径:<source_path>
和<target_path>
。我希望我的 shell (zsh) 自动找出是否有办法将<target_path>
from表示<source_path>
为相对路径。
例如,我们假设
<source_path>
是/foo/bar/something
<target_path>
是/foo/hello/world
结果将是../../hello/world
为什么我需要这个:
我需要创建一个符号链接从<source_path>
到<target_path>
使用相对的尽可能使用符号链接,否则当我从 Windows 访问网络上的这些文件时,我们的 samba 服务器无法正确显示该文件(我不是系统管理员,无法控制此设置)
假设<target_path>
和<source_path>
是绝对路径,以下创建符号链接指向绝对路径。
ln -s <target_path> <source_path>
所以它不能满足我的需要。我需要对数百个文件执行此操作,因此我无法手动修复它。
有任何 shell 内置程序可以处理这个问题吗?
答案1
尝试使用realpath
命令(GNU 的一部分coreutils
;>=8.23),例如:
realpath --relative-to=/foo/bar/something /foo/hello/world
如果您使用的是 macOS,请通过以下方式安装 GNU 版本:brew install coreutils
并使用grealpath
.
请注意,两个路径都需要存在才能使命令成功。如果您无论如何都需要相对路径,即使其中之一不存在,请添加 -m 开关。
有关更多示例,请参阅将绝对路径转换为给定当前目录的相对路径。
答案2
您可以使用以下symlinks
命令将绝对路径转换为相对路径:
/tmp$ mkdir -p 1/{a,b,c} 2
/tmp$ cd 2
/tmp/2$ ln -s /tmp/1/* .
/tmp/2$ ls -l
total 0
lrwxrwxrwx 1 stephane stephane 8 Jul 31 16:32 a -> /tmp/1/a/
lrwxrwxrwx 1 stephane stephane 8 Jul 31 16:32 b -> /tmp/1/b/
lrwxrwxrwx 1 stephane stephane 8 Jul 31 16:32 c -> /tmp/1/c/
我们已经有了绝对链接,让我们将它们转换为相对链接:
/tmp/2$ symlinks -cr .
absolute: /tmp/2/a -> /tmp/1/a
changed: /tmp/2/a -> ../1/a
absolute: /tmp/2/b -> /tmp/1/b
changed: /tmp/2/b -> ../1/b
absolute: /tmp/2/c -> /tmp/1/c
changed: /tmp/2/c -> ../1/c
/tmp/2$ ls -l
total 0
lrwxrwxrwx 1 stephane stephane 6 Jul 31 16:32 a -> ../1/a/
lrwxrwxrwx 1 stephane stephane 6 Jul 31 16:32 b -> ../1/b/
lrwxrwxrwx 1 stephane stephane 6 Jul 31 16:32 c -> ../1/c/
参考
答案3
我认为这个 python 解决方案(取自这个答案)也值得一提。将其添加到您的~/.zshrc
:
relpath() python -c 'import os.path, sys;\
print os.path.relpath(sys.argv[1],sys.argv[2])' "$1" "${2-$PWD}"
然后你可以这样做,例如:
$ relpath /usr/local/share/doc/emacs /usr/local/share/fonts
../doc/emacs
答案4
# Prints out the relative path between to absolute paths. Trivial.
#
# Parameters:
# $1 = first path
# $2 = second path
#
# Output: the relative path between 1st and 2nd paths
relpath() {
local pos="${1%%/}" ref="${2%%/}" down=''
while :; do
test "$pos" = '/' && break
case "$ref" in $pos/*) break;; esac
down="../$down"
pos=${pos%/*}
done
echo "$down${ref##$pos/}"
}
这是解决问题的最简单、最漂亮的方法。
它也应该适用于所有类似 bourne 的 shell。
这里的智慧是:完全不需要外部公用设施,甚至不需要复杂的条件。在类似 bourne 的 shell 上完成任何事情只需要几个前缀/后缀替换和一个 while 循环。
也可通过 PasteBin 获取:http://pastebin.com/CtTfvime