这将删除以.a
或.b
$ ls *.a
a.a b.a c.a
$ ls *.b
a.b b.b c.b
$ rm *.a *.b
除了以*.*
和*.a
结尾的文件外,我将如何反复删除以*.b
结尾的所有文件?
答案 0 :(得分:1)
您可以在bash中启用扩展的glob:
shopt -s extglob
然后你可以使用:
rm *.!(a|b)
删除所有以*.*
结尾的文件,但以*.a
或*.b
更新:(感谢@ mklement0)这是一种通过在extglob
中执行此操作来本地化设置subshell
(不改变全局状态)并使用中间变量:
(shopt -s extglob; glob='*.!(a|b)'; rm $glob)
答案 1 :(得分:1)
链接的答案提供了有用的信息,虽然这个问题有点含糊不清,答案使用了不同的解释。
您案例中最简单的方法可能是({3}}的简化版本):
(GLOBIGNORE='*.a:*.b'; rm *.*)
(...)
)来本地化设置GLOBIGNORE
变量。GLOBIGNORE
的模式必须为:
- 已分隔。此方法的吸引力在于您可以使用单个子shell而不更改全局状态。
相比之下,使用shopt -s extglob
获得单个子shell需要一些技巧:
(shopt -s extglob; glob='*.!(a|b)'; echo $glob)
请注意强制使用中间变量,如果没有该中间变量,命令将中断(因为在执行命令之前将扩展文字glob,此时尚未识别扩展的globbing语法)
警告:使用GLOBIGNORE
会产生意想不到的副作用(错误?):
如果GLOBIGNORE
设置 - 任何值 - *
和*.*
的路径名扩展就像shell选项dotglob
生效一样 - 即使它不是
换句话说:如果设置了GLOBIGNORE
,GLOBIGNORE
中的模式未明确豁免的隐藏文件总是匹配{{ 1}}和*
。
*.*
默认为OFF,导致dotglob
不包含隐藏的文件(如果未设置*
,默认情况下为true)。< / p>
如果您还想在使用GLOBIGNORE
时排除隐藏文件,请添加以下模式:GLOBIGNORE
;适用于这个问题,你得到:
.*
相比之下,在启用 (GLOBIGNORE='*.a:*.b:.*'; rm *.*)
shell选项后使用扩展通配符会尊重extglob
选项。
答案 2 :(得分:0)
有一些shell能够做到这一点(我认为?),但是bash
默认不是。如果您在Cygwin上运行bash
,则可以执行以下操作:
rm $(ls -1 | grep -v '.*\.a' | grep -v '.*\.b')
ls -1
(这是一个)列出当前目录中每行一个文件。grep -v '.*\.a'
返回不以.a grep -v '.*\.b'
返回不以.b 答案 3 :(得分:0)
有时候最好不要坚持以某种方式解决问题。对于“以某种棘手的方式对某些文件采取行动”的一般问题,find
可能是您能找到的最好的全能工具。
find . -type f -maxdepth 1 ! -name \*.[ab] -delete
如果要递归到子目录,请忽略-maxdepth 1
。