为什么使用find命令时,zsh的文件名扩展无法正常工作?

27

我一直在使用zsh globbing来运行命令,例如:

 vim **/filename
 vim *.html.erb

等等,但当我输入类似以下内容时:

 find . -name *mobile*

我得到的响应是:

 zsh: no matches found: *mobile*

为什么?


2
我认为这里有一个更好的答案:https://unix.stackexchange.com/questions/130958/scp-wildcard-not-working-in-zsh - Syed Ali
特别是这个答案:https://unix.stackexchange.com/a/130967/13732 - ThomasW
3个回答

58
find . -name *mobile* # does not work

vs

find . -name '*mobile*' # works

区别在于Shell解析一行命令时所采取的步骤。通常,Shell在运行命令之前会扩展它发现的任何通配符。但是,单引号将参数标记为字面量,这意味着Shell在运行命令之前不对该参数执行通配符扩展。

为了演示差异,请假设您在具有以下文件的目录中:

$ tree
./
mobile.1
dir/
    mobile.2

在第一种情况下,没有单引号,zsh 将进行以下处理:

  • 展开 glob,只留下当前目录中匹配的文件名 mobile.1
  • 将结果传递给 find,因此:
find . -name mobile.1

find命令只会查找文件名字面上为mobile.1的文件。

在第二种形式中,使用单引号,整个glob模式将被保留并传递给find

find . -name *mobile*

这意味着find将查找包含字符串“mobile”的任何文件名。

需要注意的重要事项是,zsh和find都支持相同的通配符语法;通过使用单引号,您可以诱使find在此情况下处理通配符,而不是zsh。


4
原来解决问题的方法很简单,只需在输入内容周围加上引号即可。
find . -name '*mobile*'

目前我还没有确切的答案为什么会出现这种情况...而且文档中也没有明显的解释,如果你知道答案,请告诉我!


1

为了档案目的,这里是我对@Swiss上面回答进行的大规模编辑/重新格式化。每次我尝试编辑时,编辑队列都已经满了好几个小时,所以我想保存这份资料以备将来参考。希望这被认为是有建设性的。

要非常清楚,这是对另一个人的工作进行的修订。


find . -name *mobile* # does not work

vs

find . -name '*mobile*' # works

这个差异是由解析一行时shell所采取的步骤造成的。通常,shell在运行命令之前会扩展它发现的任何通配符。然而,单引号将参数标记为文字,这意味着shell在运行命令之前不会对该参数执行通配符扩展。

为了说明区别,假设您在一个目录中有以下文件:

$ tree
./
mobile.1
dir/
    mobile.2

在第一种情况下,即不使用单引号,zsh将按以下方式处理:
  • 展开glob,变成简单的mobile.1(因为这是当前目录中唯一匹配的文件名)
  • 将结果传递给find,因此:
find . -name mobile.1

因此,find 只会查找文件名为 mobile.1 的文件。

在第二种形式中,使用单引号,整个 glob 将被保留并传递给 find

find . -name *mobile*

这意味着find将寻找包含字符串“mobile”的任何文件名。

需要注意的重要事项是,zsh和find都支持相同的通配符语法;通过使用单引号,您可以诱使find在此情况下处理通配符,而不是zsh。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接