Shell 删除除具有特定扩展名的文件以外的所有文件
这将删除以Shell 删除除具有特定扩展名的文件以外的所有文件,shell,cygwin,rm,Shell,Cygwin,Rm,这将删除以.a或.b结尾的所有文件 $ ls *.a a.a b.a c.a $ ls *.b a.b b.b c.b $ rm *.a *.b 我该如何做相反的事情,删除所有以*.*.结尾的文件,除了那些以*.a和*.b结尾的文件?有一些shell可以做到这一点(我想?),但是,bash在默认情况下不是这样的。如果您正在Cygwin上运行bash,则可以执行以下操作: rm $(ls -1 | grep -v '.*\.a' | grep -v '.*\.b') ls-1(这
.a
或.b
结尾的所有文件
$ ls *.a
a.a b.a c.a
$ ls *.b
a.b b.b c.b
$ rm *.a *.b
我该如何做相反的事情,删除所有以
*.*.
结尾的文件,除了那些以*.a
和*.b
结尾的文件?有一些shell可以做到这一点(我想?),但是,bash
在默认情况下不是这样的。如果您正在Cygwin上运行bash
,则可以执行以下操作:
rm $(ls -1 | grep -v '.*\.a' | grep -v '.*\.b')
(这是一个)列出当前目录中的所有文件,每行一个ls-1
返回所有不以.a结尾的匹配项grep-v'.*\.a'
返回所有不以.b结尾的匹配项grep-v'.*\.b'
shopt -s extglob
然后您可以使用:
rm *.!(a|b)
删除除以*.a
或*.b
结尾的文件外的所有以*.a
或*.b
结尾的文件
更新:(感谢@mklement0)以下是一种本地化设置extglob
(不改变全局状态)的方法,方法是在子shell中执行此操作并使用中间变量:
(shopt -s extglob; glob='*.!(a|b)'; rm $glob)
有时候最好不要坚持用某种方式解决问题。对于“以某种棘手的方式处理某些文件”的一般问题,find
可能是最好的全方位工具
find . -type f -maxdepth 1 ! -name \*.[ab] -delete
如果要递归到子目录中,请省略-maxdepth 1
。链接的答案包含有用的信息,尽管问题有些含糊不清,答案使用不同的解释
在您的情况下,最简单的方法可能是(简化版的):
- 注意使用子shell(
(…)
)来本地化GLOBIGNORE
变量的设置
- 分配给
GLOBIGNORE
的模式必须分开
这种方法的吸引力在于,您可以在不更改全局状态的情况下使用单个子shell
相比之下,使用shopt-s extglob
获得单个子shell需要一些技巧:
(shopt -s extglob; glob='*.!(a|b)'; echo $glob)
请注意,必须使用中间变量,如果没有中间变量,命令将中断(因为在执行命令之前将扩展文本glob,此时扩展的globbing语法尚未识别)
警告:使用GLOBIGNORE
会产生意外的副作用(bug?):
如果将GLOBIGNORE
设置为任意值,则*
和*.
的路径名扩展将表现为shell选项dotglob
有效,即使它无效。
换句话说:如果设置了GLOBIGNORE
,则未被GLOBIGNORE
中的模式明确豁免的隐藏文件始终由*
和*.
匹配
默认情况下,dotglob
处于关闭状态,导致*
不包含隐藏文件(如果未设置GLOBIGNORE
,默认情况下为true)
如果您还希望在使用GLOBIGNORE
时排除隐藏文件,请添加以下模式:*
;应用于这个问题,你会得到:
(GLOBIGNORE='*.a:*.b:.*'; rm *.*)
相比之下,在打开extglob
shell选项后使用扩展globing确实尊重dotglob
选项。类似用法的可能重复shopt-u extglob
禁用TKS,希望使用一个变量,以便我可以添加其他不被删除的条件。@HattrickNZ从另一篇文章中看到。在启用extglob
的情况下,您的bash可能支持这种风格的语法:rm!(*.a |*.b)
在这种情况下,您可以使用变量。@HattrickNZ事实上,我可以验证这是否有效:shopt-s extglob;rm_all_but=“*.a |*.b”;rm!($rm_all_,but)
。请记住,extglob
将保持启用状态……我必须查找extglob
,感谢您找到了中间变量技术,允许将shopt-s extglob
和使用扩展glob放在同一行上。如果你把它放在一个子shell中,设置extglob
会被有效地本地化(没有保持启用状态):(shopt-s extglob;glob='!(*.a |*.b);rm$glob)
。受@savanto评论的启发,我找到了一种通过子shell本地化设置extglob
(即不改变全局状态)的方法:(shopt-s extglob;glob='*.!(a | b)';rm$glob)
-注意中间变量的强制使用。
(GLOBIGNORE='*.a:*.b:.*'; rm *.*)