【问题标题】:Using find - Deleting all files/directories (in Linux ) except any one使用 find - 删除所有文件/目录(在 Linux 中),除了任何一个
【发布时间】:2011-08-05 07:05:39
【问题描述】:

如果我们想删除我们使用的所有文件和目录,rm -rf *

但是如果我想一次性删除所有文件和目录,除了一个特定的文件?

有什么命令吗? rm -rf * 提供了一次删除的便利,但甚至删除了我最喜欢的文件/目录。

提前致谢

【问题讨论】:

    标签: linux file shell


    【解决方案1】:

    find可以是很好的朋友:

    $ ls
    a/  b/  c/
    $ find * -maxdepth 0 -name 'b' -prune -o -exec rm -rf '{}' ';'
    $ ls
    b/
    $ 
    

    解释:

    • find * -maxdepth 0: 选择* 选择的所有内容,而不降级到任何目录

    • -name 'b' -prune:不要打扰 (-prune) 任何符合条件 -name 'b'

    • -o -exec rm -rf '{}' ';':其他一切都请致电rm -rf

    顺便说一句,另一种可能更简单的方法是移动或重命名您的 favourite 目录,使其不碍事:

    $ ls
    a/  b/  c/
    $ mv b .b
    $ ls
    a/  c/
    $ rm -rf *
    $ mv .b b
    $ ls
    b/
    

    【讨论】:

    • 可以改进:find * -maxdepth 0 -name 'b' -prune -o -exec rm -rf {} \;
    • @maveric:同意,我就是这么写的,但我不想在这个答案中涉及涉及引用和转义的各种 shell 复杂性......
    • 你能不能生成不包括要“保护”的文件的文件列表,然后将其通过管道传送到xargs,而不是使用-exec为每个匹配生成rm
    • @Noufal:不可移植 - 许多xargs 变体没有-0,这在处理空白时往往会使事情变得更容易。
    • @Noufal:见this cmets 中有相当多的可移植性信息。
    【解决方案2】:

    简答

    ls | grep -v "z.txt" | xargs rm
    

    详情

    上述命令的思考过程是:

    • 列出所有文件 (ls)
    • 忽略一个名为“z.txt”的文件(grep -v“z.txt”)
    • 删除除 z.txt (xargs rm) 以外的列出的文件

    例子

    如下图创建5个文件:

    echo "a.txt b.txt c.txt d.txt z.txt" | xargs touch
    

    列出除 z.txt 以外的所有文件

    ls|grep -v "z.txt"
    
    a.txt
    b.txt
    c.txt
    d.txt
    

    我们现在可以使用 xargs 实用程序删除(rm)列出的文件:

    ls|grep -v "z.txt"|xargs rm
    

    【讨论】:

    • 非常优雅的解决方案。简短易懂。它对我有用。
    【解决方案3】:

    您可以直接在命令行中键入它或在脚本中使用此按键

    files=`ls -l | grep -v "my_favorite_dir"`; for file in $files; do rm -rvf $file; done
    

    附:我建议-i 切换为rm 以防止删除重要数据。

    P.P.S 你可以根据这个解决方案编写小脚本并将其放置到/usr/bin(例如/usr/bin/rmf)。现在您可以将其用作普通应用程序:

    rmf my_favorite_dir
    

    脚本看起来像(只是一个草图):

    #!/bin/sh
    
    if [[ -z $1 ]]; then
        files=`ls -l`
    else
        files=`ls -l | grep -v $1`
    fi;
    
    for file in $files; do
        rm -rvi $file
    done;
    

    【讨论】:

    • 嗯,parsing the output of ls 不是一个好主意 - 这是一个不应该传播给其他人的坏习惯。并且您的 for 循环会遇到包含空格的文件名问题...
    • 不知道。感谢您的提示:)
    【解决方案4】:

    至少在zsh中

    rm -rf ^filename
    

    如果您只想保留一个文件,可以选择。

    【讨论】:

      【解决方案5】:

      如果它只是一个文件,一种简单的方法是将该文件移动到/tmp 或其他东西,rm -Rf 目录,然后将其移回。您可以将其别名为一个简单的命令。

      另一种选择是先执行 find 然后 grep 删除您不想要的内容(使用 -v 或直接使用 finds 谓词之一),然后 rming 其余文件.

      对于单个文件,我会做前者。除此之外,我会写一些类似于 thkala 所说的自定义内容。

      【讨论】:

        【解决方案6】:

        在 bash 中,您有 !() glob 运算符,它反转匹配的模式。所以要删除文件my_file_name.txt以外的所有内容,试试这个:

        shopt -s extglob
        rm -f !(my_file_name.txt)
        

        查看这篇文章了解更多详情: http://karper.wordpress.com/2010/11/17/deleting-all-files-in-a-directory-with-exceptions/

        【讨论】:

          【解决方案7】:

          我不知道有这样的程序,但我过去一直想要它。基本语法是:

          IFS='
          ' for f in $(except "*.c" "*.h" -- *); do
            printf '%s\n' "$f"
          done
          

          我想到的程序有三种模式:

          • 精确匹配(使用选项-e
          • glob 匹配(默认,如上例所示)
          • 正则表达式匹配(使用选项-r

          它需要从命令行中排除的模式,后跟分隔符--,然后是文件名。或者,可以从stdin 读取文件名(如果给出了选项-s),每个文件名都在一行中。

          这样的程序应该不难用 C 或 Shell 命令语言编写。它为学习 Unix 基础知识提供了很好的练习。当然,当您作为 shell 程序执行此操作时,您必须注意包含空格和其他特殊字符的文件名。

          【讨论】:

          • 您要求的是find 的简单包装器
          • 不,我想要一个通用工具。也许我想cp 除了.svn 之外的一些文件,也许我想呼应他们的名字。 find 的问题在于它不知道所有系统上的 -maxdepth 选项。见pubs.opengroup.org/onlinepubs/009695399/utilities/find.html
          【解决方案8】:

          我在这里看到了很多冗长的方法,这很有效,但是 a/ b/ c/ d/ e/

           rm -rf *.* !(b*) 
          

          这将删除除目录 b/ 及其内容之外的所有内容(假设您的文件位于 b/. 然后只需 cd b/ 和

          rm -rf *.* !(filename) 
          

          删除所有其他内容,但要保留的文件(名为“文件名”)。

          【讨论】:

            【解决方案9】:
            mv subdir/preciousfile  ./
            rm -rf subdir
            mkdir subdir
            mv preciousfile subdir/
            

            这看起来很乏味,但是相当安全

            • 避免复杂的逻辑
            • 永远不要使用rm -rf *,它的结果取决于您当前的目录(可能是/ ;-)
            • 永远不要使用通配符*:它的扩展受限于 ARGV_MAX。
            • 允许您在每个命令后检查错误,并可能避免下一个命令造成的灾难。
            • 避免了由文件名中的空格或 NL 引起的严重问题。

            【讨论】:

              【解决方案10】:
              cd ..
              ln trash/useful.file ./
              rm -rf trash/*
              mv useful.file trash/
              

              【讨论】:

              • 注意:这不适用于跨文件系统边界。例如如果 trash. 位于不同的文件系统上
              • Dezza,我从来没有在这种情况下考虑过它......无论如何,现在我知道'nota bene'是什么:)
              【解决方案11】:

              您需要为此使用正则表达式。编写一个正则表达式,选择除您需要的文件之外的所有其他文件。

              【讨论】:

              • 正则表达式是一种的方法,但你并不需要它们。
              • 正则表达式输入 what?大多数 shell 只使用简单的 glob 表达式。
              猜你喜欢
              • 2015-09-02
              • 1970-01-01
              • 2011-08-19
              • 1970-01-01
              • 1970-01-01
              • 2014-03-13
              • 2018-05-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多