我最近从 bash 切换到 zsh,现在当我输入时
ls *
它并不简单地列出该目录中的所有文件,而是显示一个两层的树。
还
rm -rf somepath/*
输出失败zsh: no matches found:
这曾经在 bash 中工作得很好。谁能帮助我恢复这种行为?
我确实安装了 oh-my-zsh。
答案1
ls *
在 bash 中也会有同样的效果。无论 shell 是什么,发生的情况都是 shell 首先扩展通配符,然后将扩展结果传递给命令。例如,假设当前目录包含四个条目:两个子目录dir1
和dir2
,以及两个常规文件file1
和file2
。然后外壳扩展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
会看到参数-rf
和somepath/*
。尝试删除目录 中rm
调用的文件,由于不存在这样的文件,因此此尝试失败。由于您将选项传递给,因此它不会抱怨丢失文件。*
somepath
-f
rm
在 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
。它允许一些模式扩展到无,只要最后一个才不是。