如何让 zsh 中的星号“*”具有与 bash 相同的行为?

如何让 zsh 中的星号“*”具有与 bash 相同的行为?

我最近从 bash 切换到 zsh,现在当我输入时

ls *

它并不简单地列出该目录中的所有文件,而是显示一个两层的树。

rm -rf somepath/*

输出失败zsh: no matches found:

这曾经在 bash 中工作得很好。谁能帮助我恢复这种行为?

我确实安装了 oh-my-zsh。

答案1

ls *在 bash 中也会有同样的效果。无论 shell 是什么,发生的情况都是 shell 首先扩展通配符,然后将扩展结果传递给命令。例如,假设当前目录包含四个条目:两个子目录dir1dir2,以及两个常规文件file1file2。然后外壳扩展ls *ls dir1 dir2 file1 file2。该ls命令首先列出现有非目录的参数名称,然后依次列出每个目录的内容。

$ ls
dir1  dir2  file1  file2
$ ls -F
dir1/  dir2/  file1  file2
$ ls *
file1  file2

dir1:

dir2:

如果ls在 bash 中表现不同,你要么更改了 bash 配置关闭通配符扩展,这会在所有地方关闭它,或者您更改了命令的含义ls以抑制目录列表(可能使用别名)。具体来说,有

alias ls='ls -d'

在你的~/.bashrc将达到你所描述的效果。如果你就是这样做的,你可以复制这一行~/.zshrc,你会得到同样的效果。


事实上,rm -rf somepath/*当 bash 和 zsh 是空目录时,效果不同somepath是完全不同的事情。

在 bash 中,如果somepath/*不匹配任何文件,则 bash 会在命令中保留通配符模式,因此rm会看到参数-rfsomepath/*。尝试删除目录 中rm调用的文件,由于不存在这样的文件,因此此尝试失败。由于您将选项传递给,因此它不会抱怨丢失文件。*somepath-frm

在 zsh 中,默认情况下,如果通配符不匹配任何文件,zsh 会将其视为错误。您可以通过关闭该选项来更改 zsh 的行为方式nomatch

setopt no_nomatch

我不建议这样做,因为让 shell 告诉您通配符何时不匹配通常是命令行上更好的行为。有一个更好的方法来告诉 zsh 在这种情况下,空列表就可以了:

rm -rf somepath/*(N)

N是一个全局限定符这表示如果通配符与任何文件都不匹配,则扩展为空列表。

答案2

您已使用非默认选项 来配置 Bourne Again shell nullglob。这使得ls *空目录变成 plain ls,而rm -rf somepath/*该子目录为空的地方变成rm -rf.

要使用 Z shell 实现相同的效果,您需要一个类似的同名非默认选项:

setopt nullglob

Z shell 有另一个选项,可以打开稍微不同的行为:

setopt cshnullglob
使用此选项,ls *rm -rf somepath/*仍然被标记为匹配错误,但rm -rf empty/* hasfiles/*不是并且忽略empty/*,不将其传递给rm。它允许一些模式扩展到无,只要最后一个才不是。

相关内容