【问题标题】:Remove all files except files with certain extension删除除具有特定扩展名的文件之外的所有文件
【发布时间】:2014-07-25 20:36:36
【问题描述】:

这会删除所有以.a.b 结尾的文件

$ ls *.a
a.a  b.a  c.a

$ ls *.b
a.b  b.b  c.b

$ rm *.a *.b

我将如何做相反的事情并删除所有以*.* 结尾的文件,但以*.a*.b 结尾的文件除外?

【问题讨论】:

标签: shell cygwin rm


【解决方案1】:

链接的答案包含有用的信息,尽管问题有些模棱两可,并且答案使用不同的解释。

在您的情况下,最简单的方法可能是(https://stackoverflow.com/a/10448940/45375 的简化版本):

 (GLOBIGNORE='*.a:*.b'; rm *.*)
  • 注意使用子shell ((...)) 来本地化设置GLOBIGNORE 变量。
  • 分配给GLOBIGNORE 的模式必须是: 分隔的。

这种方法的吸引力在于您可以在不更改全局状态的情况下使用单个子shell

相比之下,使用shopt -s extglob 摆脱单个子shell 需要一些技巧

(shopt -s extglob; glob='*.!(a|b)'; echo $glob)

注意中间变量的强制使用,没有它,命令将中断(因为在执行命令之前会扩展文字 glob,此时扩展的 glob 语法尚未识别) .


警告:使用GLOBIGNORE 会产生意想不到的副作用(错误?):

如果 GLOBIGNOREset - 任何值 - **.* 的路径名扩展就像 shell 选项 dotglob 生效一样 - 即使它不是。
换句话说:如果设置了GLOBIGNORE隐藏文件没有被GLOBIGNORE中的模式明确排除在总是*匹配和*.*

dotglob 默认关闭,导致* 不包含隐藏 文件(如果GLOBIGNORE 未设置,默认为true)。

如果您还想在使用GLOBIGNORE排除隐藏文件,请添加以下模式:.*;应用于这个问题,你会得到:

 (GLOBIGNORE='*.a:*.b:.*'; rm *.*)

相比之下,在打开extglob shell 选项后使用扩展通配符确实尊重dotglob 选项。

【讨论】:

    【解决方案2】:

    您可以在 bash 中启用扩展 glob:

    shopt -s extglob
    

    那么你可以使用:

    rm *.!(a|b)
    

    删除所有以*.* 结尾的文件,除了以*.a*.b 结尾的文件

    更新:(感谢@mklement0)这是一种本地化设置extglob(不改变全局状态)的方法,方法是在subshell 中执行此操作并使用中间变量:

    (shopt -s extglob; glob='*.!(a|b)'; rm $glob)
    

    【讨论】:

    • 受@savanto 评论的启发,我想出了一种方法来localize 通过子shell 设置extglob(即不改变全局状态): (shopt -s extglob; glob='*.!(a|b)'; rm $glob) - 注意中间变量的强制使用。
    【解决方案3】:

    有些 shell 可以做到这一点(我认为?),但是 bash 不是默认的。如果你在 Cygwin 上运行 bash,你可以这样做:

    rm $(ls -1 | grep -v '.*\.a' | grep -v '.*\.b')
    
    • ls -1(这是一个)列出当前目录中的所有文件,每行一个。
    • grep -v '.*\.a' 返回所有以 .a 结尾的匹配项
    • grep -v '.*\.b' 返回所有以 .b 结尾的匹配项

    【讨论】:

    • tks,希望使用一个变量,以便我可以添加其他不被删除的标准。
    • @HattrickNZ 请参阅另一篇帖子中的this answer。您的 bash 可能支持这种样式语法,启用 extglobrm !(*.a|*.b) 在这种情况下您可以使用变量。
    • @HattrickNZ 事实上,我可以验证这是否有效:shopt -s extglob; rm_all_but="*.a|*.b"; rm !($rm_all_but)。请记住,extglob 将保持启用状态...
    • 我得查一下extglob
    • 感谢您找出中间变量技术以允许将shopt -s extglob 和在同一行上使用扩展 glob。如果你把它放在 subshel​​l 中,设置 extglob 实际上是 localized(未启用):(shopt -s extglob; glob='!(*.a|*.b)'; rm $glob)
    【解决方案4】:

    有时最好不要坚持以某种方式解决问题。对于“以某种棘手的方式对某些文件进行操作”这一普遍问题,find 可能是您能找到的最好的全能工具。

    find . -type f -maxdepth 1 ! -name \*.[ab] -delete
    

    如果您想递归到子目录,请省略 -maxdepth 1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      相关资源
      最近更新 更多