我可以仅在使用通配符时使 `rm` 交互吗?(在 bash 或 zsh 或两者中)

ico*_*ast 15 bash zsh wildcards rm

每当我rm使用 shell globbing 同时处理多个项目并且模式扩展到超出我预期的最轻微的可能性时,我总是尝试记住添加-i,但是(当然)我可能会忘记并意外地吹走一些有用的东西。有些人试图用别名来解决这个问题,比如alias rm='rm -i'但我讨厌让 rm总是交互的想法,因为那样我会养成一直使用的习惯-f,这显然会破坏整个目的。

我想做的是rm-i在我使用通配符时使用,并且-f当然要覆盖-i,所以我仍然可以用通常的rm -rf junk.

因此rm *blah*,确实会,rm -i *blah*rm blah会完全按照键入的方式工作。

如果这在不同的 shell 中实现方式有所不同,我将选择一个为 bashzsh提供方法的答案,而不是仅涵盖其中一个的答案。


注意:我实际上并不相信这一定是个好主意;我只是问是否有可能。如果您认为这是一个愚蠢的想法,我会很高兴听到您的意见背后的原因,但请不要在答案字段中发表此类评论。真正的答案要么告诉我如何做到这一点,要么解释/为什么不可能(或者可能提供一种替代方法来获得类似的结果)。但如果你想告诉我为什么这是愚蠢的,请发表评论。即使我不同意结论,我也会赞成合理的评论。

Sté*_*las 9

这是不容易的。问题是当你这样做时:

rm -- *.txt
Run Code Online (Sandbox Code Playgroud)

rm 只看到文件列表,而不是已经被 shell 展开的通配模式。

你可以做的是(zsh):

alias rm='noglob rm'
Run Code Online (Sandbox Code Playgroud)

这告诉 zsh 在调用 rm 时不应扩展模式。然后你可以将 rm 重新定义为一个函数,它自己进行扩展并在需要时添加“-i”,例如:

'rm'() {
  [[ "$*" = *[*[?]* ]] && set -- -i "$@"
  command rm $~@
}
Run Code Online (Sandbox Code Playgroud)

但是这种方法的问题是这个新的“rm”没有看到之间的区别

rm *
Run Code Online (Sandbox Code Playgroud)

rm '*'
Run Code Online (Sandbox Code Playgroud)

要删除名为 的文件*,您必须编写它:

rm [*]
Run Code Online (Sandbox Code Playgroud)