【问题标题】:How to make rm not delete symbolic links?如何让 rm 不删除符号链接?
【发布时间】:2020-10-19 13:15:42
【问题描述】:

所以,我删除了不需要的文件并删除了一些文件夹。一段时间后,我看到另一个文件夹在ls -la 中显示为红色。我知道我删除了实际的文件夹,因此我很伤心,并试图运行foremost 来恢复,但运气不好。谁能给我一些像 rm -rf 这样删除的好别名/函数,但如果该文件链接到其他文件,那么它将不会被删除。就像如果/usr/bin/a.py 链接到/root/a.py 并且我运行rm -rf /usr/bin/a.py 那么/root/a.py 将被删除。如何防止别名出现这种情况?

【问题讨论】:

  • 有两个文件夹,所以我删除了一个垃圾文件夹,但另一个被删除了:(
  • @DipsehSunrait :删除符号链接只会删除链接,而不是链接到的文件,至少只要您不使用-r。

标签: bash git terminal rm ln


【解决方案1】:

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

这是previous treatment 的“删除指向目录的符号链接而不删除目标”,其中对哪些有效哪些无效的分析不太彻底,但提供了一堆其他有用的信息。


不幸的是,我不知道有什么方法可以给 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 在做有潜在危险的事情时提示。

【讨论】:

    【解决方案2】:

    我不认为它的行为方式与您所指示的方式相同。 rm 不遵循符号链接

    删除某些内容的唯一方法是执行rm -rf myFolder/* 之类的操作,其中myFolder 是链接目录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 2014-02-20
      • 2020-11-10
      • 2010-09-17
      • 2018-12-01
      • 2012-08-28
      相关资源
      最近更新 更多