是否有非递归readlink -f
/realpath
替代方案可以输出绝对符号链接目标?也欢迎更多 POSIX 兼容的解决方案。
我的 shell 脚本中有一个功能块,如下所示:
set FILES
# addFile adds a file to the FILES list. If file is a symlink,
# it will also find and add the destination.
addFile() {
file="$1"
# Check if file is already included in list
echo "$FILES" | grep -q "$file" && return
FILES="$FILES $file"
if [ -L $file ]; then
addFile $(realpath $file)
#addFile $(readlink $file)
fi
}
我在一个脚本中使用此函数,该脚本从文件系统收集二进制文件和库文件。但我预见到这段代码有一个问题:
- 我的第一次尝试使用了
readlink
,但这返回了相对于 的符号链接解析路径$file
,因此在这些路径上执行的任何操作都会失败。 (现在已注释掉,但仍在代码中)(请参阅下面的小编辑) - 之后,我
realpath
按照建议使用了man readlink
。几乎可以用了。
现在,我想要执行的操作可以正常工作了。但是,最终结果是,我将复制 initramfs 中的所有二进制文件、库和符号链接。如果有任何递归符号链接,则只会包含顶层和目标,而不会包含中间的符号链接。因此,符号链接被破坏了。
我创建了一个小提琴来演示这个问题。link-to-link1
指向link1
,它指向file1
。最终结果link1
丢失并被link-to-link1
破坏。
编辑;澄清问题
在以下一组符号链接上运行上述函数时:
# Contents of ~/test/src
file0
file1
link0 -> file0
link0.1 -> file0
link1 -> file1
link-to-link1 -> link1
和:
copy="link-to-link1 link0 link0.1"
for sf in $copy; do
addFile ~/test/src/$sf
done;
cp -av $FILES ~/test/dst
$copy
您会发现仅复制了3 个链接和 2 个文件。然而,中间环节link1
缺失且link-to-link1
已损坏。
link1
我也希望找到该脚本。请记住,在运行此脚本的环境中,文件和符号链接的位置必须是绝对的。
小修改
添加另一个小提琴为了演示相对路径的失败,使用readlink
.仅复制符号链接,并且缺少目标。
答案1
如果我理解正确,对于给出的示例,您想要link1
文件link-to-link1
.您可以使用 GNUfind
的-printf
和来获得%l
:
$ find . -type l -printf '%p -> %l\n'
./link0.1 -> file0
./link1 -> file1
./link0 -> file0
./link-to-link1 -> link1
由于需要 的绝对路径link1
作为 的输出/path/to/link-to-link1
,可能是包含并连续运行/ 的cd
目录:link-to-link1
readlink
realpath
(
cd "$(dirname "$file")"
realpath -s "$(readlink "$file")"
)
realpath -s
不解析符号链接,但会打印绝对路径。
例如:
~ file=/tmp/foo/link-to-link1
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1
这也适用于绝对路径的链接:
~ file=/tmp/foo/link2
~ ln -sfv /tmp/foo/link1 "$file"
'/tmp/foo/link2' -> '/tmp/foo/link1'
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1