bash - 如何让 rm 不删除符号链接?
问题描述
所以,我正在摆脱不需要的文件,并删除了一些文件夹。过了一段时间,我看到另一个文件夹在ls -la
. 我知道我删除了实际的文件夹,因此我非常难过并试图跑去foremost
恢复但运气不好。谁能给我一些像 rm -rf 这样删除的好别名/函数,但如果该文件链接到其他文件,那么它将不会被删除。就像如果/usr/bin/a.py
链接到/root/a.py
并且我运行rm -rf /usr/bin/a.py
然后/root/a.py
将被删除。我怎样才能防止别名呢?
解决方案
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
这些都是安全的:
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
这是以前的“删除目录的符号链接而不删除目标”的处理方法,对哪些有效,哪些无效,但有一堆其他有用的信息进行了不太彻底的分析。
不幸的是,我不知道有什么方法可以使用别名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 "$@"
}
不过,使用风险自负!它通过了 shellcheck 并且在我测试它时有效,但是在基本和危险的东西之上实现了一个包装器,就像rm
给了我 heebie-jeebies 一样。
您可能在别名/功能中包含的另外两个潜在有用的开关是--one-file-system
(至少跳过符号链接的文件或安装到不同的驱动器上),如果您还没有使用它,-i
或者-I
在做一些潜在危险的事情时提示。
推荐阅读
- c++ - 将定义的类声明为模板参数内的结构
- r - 在多个数据帧上应用 ddply
- go - Go 版 Stripe Checkout 教程无法编译,未定义:session
- c++ - QT 创建带有可点击项目的巨大网格
- c - 在“swscanf”中指定扫描集和“h”宽度修饰符不适用于 MSVC
- php - laravel 使用 find 时出现此错误:调用未定义的方法 Intervention\Image\ImageManager::find()
- mysql - 在 ubuntu 20.04 [POP-OS] 中安装 mySQL 时出错
- i18next - I18next 使用捆绑的翻译文件在本地加载翻译
- prometheus - 在单个 grafana 面板上添加多个警报
- php - 线程中的 PHP Curl 重用