Joe W 的答案是正确的,说rm通常不会删除符号链接的目标,但说它“不遵循符号链接”不太准确,至少在我的系统上(GNU coreutils 8.25)。而删除文件是一个非常重要的地方!让我们看一下它在几种情况下的表现。
如果您的符号链接是文件而不是目录,则没有可行的方法可以意外删除目标rm。你必须做一些非常明确的事情,比如rm "$(readlink file)".
然而,目录的符号链接有点危险,正如您不小心删除了一个符号链接时所看到的那样。这是我们可以使用的测试用例:
$ mkdir test1
$ touch test1/foo.txt
$ ln -s test1 test2
$ ls -lR
.:
total 4
drwxrwxr-x 2 soren soren 4096 Jun 29 17:02 test1
lrwxrwxrwx 1 soren soren 5 Jun 29 17:02 test2 -> test1
./test1:
total 0
-rw-rw-r-- 1 soren soren 0 Jun 29 17:02 foo.txt
Run Code Online (Sandbox Code Playgroud)
这些都是安全的:
rm test2(仅删除符号链接)rm -r test2(仅删除符号链接)rm -rf test2(仅删除符号链接)rm test2/(rm: cannot remove 'test2/': Is a directory- 不采取行动)rm -rf *2(或任何其他与符号链接匹配的 glob——仅删除符号链接)这些是不安全的:
rm -r test2/(rm: cannot remove 'test2/': Not a directory--但删除目录的内容test1)rm -rf test2/(删除目录的内容,保留符号链接,没有错误)rm -rf test2/* (删除目录的内容,保留符号链接,没有错误)最后一个不安全的情况可能是明显的行为,至少对于熟悉 shell 的人来说是这样,但是前面的两个情况更加微妙和危险,特别是因为使用制表符补全名称test2会为您删除尾部斜杠!
有趣的是,它test具有类似的行为,考虑到带有尾部斜杠的目录的符号链接不是符号链接而是目录,而没有尾部斜杠的符号链接两者都是:
$ [ -L "test2" ] && echo "is link"
is link
$ [ -d "test2" ] && echo "is directory"
is directory
$ [ -L "test2/" ] && echo "is link"
$ [ -d "test2/" ] && echo "is directory"
is directory
Run Code Online (Sandbox Code Playgroud)
这是之前对“删除目录的符号链接而不删除目标”的处理,对哪些有效、哪些无效进行了不太彻底的分析,但提供了一堆其他有用的信息。
不幸的是,我不知道有什么方法可以使用别名rm来防止这种错误。我想您可以编写一个函数来解析参数rm,并警告您是否其中任何一个是以斜杠结尾的符号链接,如下所示:
function rm {
for i in "$@"; do
if [[ $i =~ /$ ]] && [ -L "${i:0:-1}" ]; then
read -rp "Really delete symlink '$i' with trailing slash (y/n)? " result
[ "$result" != "y" ] && return
fi
done
command rm "$@"
}
Run Code Online (Sandbox Code Playgroud)
不过,使用风险需您自担!它通过了 shellcheck,并且在我测试它时它起作用了,但是在基本且危险的东西之上实现一个包装器rm让我感到惶恐不安。
您可能在别名/函数中包含的其他两个可能有用的开关是--one-file-system(至少跳过符号链接的文件或安装到不同的驱动器上),如果您尚未使用它,-i或者-I在执行潜在危险的操作时进行提示。