有没有一种简单的方法可以预览 rm 将删除的文件?

Dan*_*ane 19 rm

有没有一种简单的方法来评估rm当您不理解给定命令时(例如无法识别标志、变量等如何交互),它会做什么?

虽然ls有助于发现rm参数中的问题,ls -abc XYZ但不会列出可能受rm -abc XYZ. 理想情况下,我想输入类似的内容previewrm -abc XYZ并查看将删除的内容而不实际删除任何内容,包括使用-f标志。

我基本上想rm在测试批处理模式下运行。也就是说,我想看看如果真正运行它会采取什么行动,最好根本不接触它。因此,testout 'rm -abc XYZ'可能是真正的理想。

ori*_*ion 33

您可能rm -i会收到将删除的每个文件的提示。您可以no重复使用该yes命令(令人困惑地)通过管道输入它,以查看提示(拒绝所有提示):

yes no | rm -i files/globs/options
Run Code Online (Sandbox Code Playgroud)

编辑以回应@user63051 的评论

如果您担心危险的标志组合,您可以指定 rm -i --,之后的任何内容都不会被视为选项。这当然意味着要使-r标志起作用,您需要将它放在--.

如果您想尝试,另一个建议是创建一个dummy不属于任何现有组的用户。如果others您的文件的权限不包含write权限(通常不包含,除非您特别需要),您只需以其他用户 ( su dummy) 的身份登录并执行rm命令即可。它没有删除任何东西的权限,所以它只会抱怨它。您也可以这样做以使用上述建议(作为双重保护)。

我应该警告你,所有调用的选项rm都有点危险。我通常只是在我想运行的整个命令前加上前缀echo,看看 bash 会给命令提供什么参数(它如何扩展通配符以及它找到哪些文件)。然后,echo如果一切正常,就删除。请注意,这不会列出递归找到的文件的内容,-r但您会看到它想要销毁的目录。

本质上 -echo如果您想看看它的作用,请使用。使用--保护从失控的标志。使用-i以防万一,它会询问每一个文件,如果它要求你不想删除的东西,你会发现。只有当你真的想生成一个列表,每行一个文件时,做其他任何事情都是有意义的。

  • `是不`必须是我今天看到的最幽默的命令...... (16认同)

ale*_*xis 6

简单的方法是使用rm -i@orion描述的方式。如果你想要的东西,就不会删除任何东西,但不会调整RM的标志,你总是可以建立自己的版本rm,我们叫它preview-rm。这真的非常简单,您甚至可以在不接触实际rm源文件的情况下完成:

  1. 查找您系统版本的源rm。您可能需要下载源包或其他任何东西。GNUrm是“核心实用程序”的一部分,由两个 C 文件、rm.cremove.c和几个头文件组成。一旦您设置好编译系统实用程序,剩下的就很简单了。

  2. 创建mockrm.c包含以下内容的文件。唯一重要的部分是某些版本的rm目录通过尝试unlink()和检查错误来检测目录,因此我们需要确保它正常工作:

    #include <stdio.h>
    #include <sys/stat.h>
    #include <errno.h>
    
    int unlink(char *s)
    {
        struct stat sbuf;
        lstat(s, &sbuf);
        /* Simulate unlink error if we're asked to unlink a directory. */
        if (S_ISDIR(sbuf.st_mode)) {
            return EISDIR;
        }
    
        puts(s);
        return 0;
    }    
    
    int rmdir(char *d)
    {
      printf("%s (dir)\n", d);
      return 0;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 最后,preview-rm像这样编译你的可执行文件:

    % cc rm.c remove.c mockrm.c -o preview-rm
    
    Run Code Online (Sandbox Code Playgroud)

    中的函数mockrm.c将优先链接到 C 库提供的系统调用,为您提供rm可用于预览的无齿克隆。(在将它指向重要文件之前,请测试它是否真的有效。)

替代方案:如果您在支持该LD_PRELOAD功能的系统上(OS X 不支持),您可以通过将mockrm.c编译到共享库 ( .so) 并强制它由真实加载来获得相同的效果rm

% cc rm.c remove.c mockrm.c -o preview-rm
Run Code Online (Sandbox Code Playgroud)

但是既然您无论如何都需要更改命令调用,为什么不创建一个单独的可执行文件,如上所示。我知道将真实rm文件指向有价值的文件会有点紧张(编辑:如果你更新你的操作系统,你必须再次测试并确保rm没有以禁用包装器的方式改变。)


小智 5

当我想这样做时,我使用“find”作为 rm 的包装器。这更好(对于您想到的用例),因为:

  • 在匹配多个模式方面更灵活
  • 它可以处理比子目录(/ .tmp 等)中的 shell 通配符更多的文件名
  • 你可以做任何 rm 能做的事情,因为它包装了 rm,但更多的是,比如打印整个 rm 命令。
  • 当您使用 +(而不是 ;)作为 -exec args 的一部分时,它不会经常调用 rm,因此它的效率并不比仅运行 rm 低多少。

要列出您可能想要删除的文件:

find . -name \*.tmp
Run Code Online (Sandbox Code Playgroud)

预览删除:

find . -name \*.tmp -exec echo rm \{\} +
Run Code Online (Sandbox Code Playgroud)

要真正删除它们,只需删除“回声”:

find . -name \*.tmp -exec rm \{\} +
Run Code Online (Sandbox Code Playgroud)

或者,您可以执行更高级的搜索/删除命令,例如:

find . \( -name \*.tmp -o -iname cache -o -iname temp \) -exec rm \{\} +
Run Code Online (Sandbox Code Playgroud)

您也可以将 find 的输出通过管道传输到“xargs rm”,但使用 NUL 来分隔文件名,如下所示:

find . -name \*.tmp -print0 | xargs -0 rm
Run Code Online (Sandbox Code Playgroud)