使用 zsh 时将正则表达式传递给命令

uni*_*ria 0 zsh wildcards arguments

在 bash 中,我可以执行以下操作:

apt install blabla*

但在 zsh 我得到

zsh: no matches found: blabla*

除非当前目录中有一个名为blablabla的文件。

这也导致与删除文件问题的一个文件夹,但不删除文件夹本身是否需要sudo访问写入。

如何让 zsh 将正则表达式传递给命令?

Kus*_*nda 6

请注意,文件名通配模式不是正则表达式。它们很相似,但通配模式blabla*将匹配以 string 开头的名称blabla,而正则表达式blabla*将匹配包含 sub-string 的字符串blabl,可能后跟零个或多个a字符。

要将字符串blabla*作为参数传递给 ,apt install而不让 shell 尝试将其用作文件名 globbing pattern,请引用它:

apt install 'blabla*'
Run Code Online (Sandbox Code Playgroud)

zsh壳具有,默认情况下,NOMATCH壳选项集,其对应于failglob在壳选项bash(其通过默认在壳中设置)。当通配模式不匹配任何内容时,这将使 shell 失败并显示诊断消息。您显然也可以关闭此 shell 选项(使用unsetopt NOMATCHsetopt NO_NOMATCH),但这在sudo用于删除您无权访问的文件的情况下无济于事。

要扩展诸如 的文件名模式bla/*,需要一个 shell(该rm命令不能单独扩展 shell globbing 模式,而且很少有命令可以,因此sudo rm -rf bla/*即使您阻止当前 shell 甚至尝试扩展模式也无法工作引用它)。既然你可能无法访问读取目录的名称bla,该外壳必须要执行为用户确实可以访问的目录,如根阅读的名字。我们可以使用sudo.

要删除您无权访问的目录中的所有文件和目录,请使用sudo

sudo sh -c 'rm -rf directoryname/*'
Run Code Online (Sandbox Code Playgroud)

请注意,这不会删除隐藏的名称,为此,请使用类似

sudo bash -O dotglob -c 'rm -rf directoryname/*'
Run Code Online (Sandbox Code Playgroud)

或者

sudo zsh -c 'rm -rf directoryname/*(D)'
Run Code Online (Sandbox Code Playgroud)

或者

sudo find directoryname -mindepth 1 -delete
Run Code Online (Sandbox Code Playgroud)

或者,使用标准find

sudo find directoryname -depth ! -path directoryname -exec rm -rf {} +
Run Code Online (Sandbox Code Playgroud)

前三个命令依赖于由root 用户运行的sh -c,bash -czsh -cshell 执行的通配,而后两个命令根本不使用文件名通配。变体find还支持删除包含数千个文件的目录(如果尝试通配,这可能会生成“参数列表太长”错误)。

另一种选择,如果你真的想删除一个目录的所有内容,就是简单地删除整个目录

sudo rm -rf directoryname
Run Code Online (Sandbox Code Playgroud)

然后使用正确的所有权和权限重新创建它。