从全局匹配中排除一种模式


53

我有几个具有相同基本文件名的文件。我只想删除一个

foo.org #keep
foo.tex #delete
foo.fls #delete
foo.bib #delete
etc

如果我不需要保留一个,那么我知道可以使用rm foo.*

TLDP证明^可以取消匹配。通过反复试验,我发现

rm foo.*[^org]

可以满足我的需求,但我不太了解语法。

另外,虽然我的用例不受限制,但我认为此模式也忽略了foo.ofoo.or。这一模式如何工作的,以及什么将一个水珠忽略只有 foo.org样子?


1
作为除了@glen回答这是值得一提的是rm foo.*[^org]删除所有文件,这最后一个字符既不是or或者g,所以foo.foo也不会觉得要匹配。
jimmij 2014年

您正在使用Regular Expression。您应该小心分组字符。通过使用括号您指定一个字符类的含义,你会删除了与字母的扩展名的文件org以任何顺序。使用括号创建一个组并保留字符顺序。
马斯卡洛先生2014年

3
@ jbarker2160-并不是真正的正则表达式,通常称为glob(或文件名模式),它或多或少是正则表达式的子集-有关详细信息,请参见bash手册页的模式匹配部分。他的模式foo.*[^org]将匹配任何foo.以点后一个或多个字符开头的文件名,其中最后一个字符不是o,r或g。因此它将匹配foo.orb,但不匹配foo.orgor foo.orfoo.o。GlennJackman的答案显示了如何启用扩展模式匹配功能来取消匹配。
约翰尼

Answers:



23

在bash中,您也可以使用GLOBIGNORE="*.org"; rm -i foo*

unset GLOBIGNORE当完成。

它确实没有比更好shopt -s extglob,但是我发现它更容易记住。


5
@Ruslan那行不通。您应该做( GLOBIGNORE="*.org"; rm -i foo* )
DBedrenko

3
请注意,如果要扩展忽略的列表,请用冒号分隔,例如GLOBIGNORE="*foo*:*bar*"
phyatt

7

管道可以做什么?

ls * | grep -v "foo.org" | xargs -I {} echo {}

(显然,您可能希望在最后一个链中用rm代替echo)。


如果只需要一行就很有用。
bruceskyaus

1
更容易记住(对我来说,我经常做这种事情),并允许启动更复杂的处理:)
drevicko

1
ls -1应更可靠,以确保所有文件都通过处理grep单独
MichaelChirico

0

OP非常接近:

rm foo.*[^o][^r][^g]

尽管在这种情况下这*是不必要的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.