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

jak*_*ake 84 bash wildcards

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

foo.org #keep
foo.tex #delete
foo.fls #delete
foo.bib #delete
etc
Run Code Online (Sandbox Code Playgroud)

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

TLDP演示^否定匹配。通过反复试验,我发现

rm foo.*[^org]
Run Code Online (Sandbox Code Playgroud)

做我需要的,但我不太了解语法。

此外,虽然在我的用例中不是限制,但我认为这种模式也忽略了foo.ofoo.or。这种模式是如何工作的,一个 忽略的 globfoo.org会是什么样子?

gle*_*man 89

shopt -s extglob
echo rm foo.!(org)
Run Code Online (Sandbox Code Playgroud)

这是“福”。后跟任何非“组织”

参考:https : //www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching

  • 匹配多个文件名的语法是什么?说我想排除 .org、.png、.txt ? (4认同)

miv*_*ivk 34

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

unset GLOBIGNORE当完成。

它并不比 好shopt -s extglob,但我发现它更容易记住。

  • 注意如果要展开忽略的列表,用冒号分隔,如`GLOBIGNORE="*foo*:*bar*"` (11认同)
  • @Ruslan 那行不通。你应该做`( GLOBIGNORE="*.org"; rm -i foo* )` (8认同)
  • 不要使用分号。只需使用`GLOBIGNORE="*.org" rm -i foo*`。 (2认同)
  • 嗯,我最终需要在设置 GLOBIGNORE 和应该应用它的命令之间添加一个“&&”。我假设如果您不这样做,则会评估整个表达式并扩展所有 * 片段 - 此时设置 GLOBIGNORE 为时已晚。换句话说,对于这个例子: `GLOBIGNORE="*.org" && rm -i foo*` (2认同)
  • 感谢@consideRatio 的解释。这就是 DBedrenko 建议使用 subshel​​l 和分号的原因。OP 根本不起作用,任何起作用的版本都会留下一个需要清理的环境变量。 (2认同)

Ado*_*obe 11

一根管子能干什么?

ls * | grep -v "foo.org" | xargs -I {} echo {}
Run Code Online (Sandbox Code Playgroud)

(显然你可能想在最后一个链中用 rm 替换 echo )。

  • `ls -1` 应该更可靠,以确保所有文件都由 `grep` 单独处理 (4认同)
  • @MichaelChirico 我们有“find”,*从不*解析 ls 输出。 (3认同)