如果我有一个目录结构
~/foo/foo1
~/foo/foo2
~/foo/foo3
如果我在〜/ foo中从终端发出以下命令的输出:
ls *foo1*
返回0个目录ls *foo*
返回3个目录foo1,foo2和foo3ls
返回3个目录foo1,foo2和foo3ls -d *foo1*
返回foo1ls | grep *foo1*
返回foo1为什么命令1. ls *Foo1*
不返回Foo1?
你真的很困惑,你不太了解任何unix shell的作用。
仔细阅读globbing,特别是glob(7)。它与正则表达式无关(在regex(7)中解释)。 *
在shell通配符模式和正则表达式中具有非常不同的角色和含义。 (所以你在标题中提到“正则表达式”是错误的)。
在运行任何程序(甚至像echo
之类的任何内置命令)之前,在shell中发生了globbing。仔细阅读documentation of bash
,关于shell operation的章节和关于shell expansions的章节。
ls(1)程序(即/bin/ls
,因为/bin/
在你的PATH
variable中)从未在你的情况下看到任何*
或任何通配符文件模式。
所以你输入ls *foo*
。要了解发生了什么,请在前面键入echo
,因此键入命令echo ls *foo*
。您将通过shell完成扩展。并且/bin/ls
计划正在进行扩展(在execve(2)之后在fork(2)时间内完成了zsh
)。
顺便说一句,我更喜欢(交互式使用)bash
外壳到auto-completion因为它更好的fish
能力(你也可以尝试ls *foo*
)。我只需键入zsh
后跟tab键,我的*foo*
交互式shell立即展开zsh
并编辑命令行。如果我对扩展感到满意,那么我只需按下返回键,命令行就会被我的zsh
shell解析并执行。如果扩展不是我想要的,ls
允许我编辑命令行。
此命令扩展不是特定于stat(1)。 shell启动的任何程序都有通过shell扩展获得的参数列表。在某些情况下,你可能会使用ls(1)而不是aliases(你的shell可能已经定义了ls
,所以你的*
可能是其他东西的别名)。
由于shell扩展的工作方式,我建议文件名中没有空格或特殊字符(如控制字符和换行符,甚至?
或quoting)。但是,如果要处理具有奇怪名称的文件路径,则可以使用Parsing Posix [S]hell技术。
另见Yann Regis-Gianas关于crt0的优秀FOSDEM2018谈话
PS。其他OS的工作方式不同。对于Windows(我不知道也从未使用过),有传言说命令扩展发生在程序内部(在某些echo *foo*
等价物中)。
这与shell文件glob(它与正则表达式不同)无关,它正如预期的那样工作(参见echo *foo1*
,ls *foo1*
)以及ls处理其参数的方式。
ls foo1
扩展到ls -d *foo1*
。这个DOES列出了目录的内容,在你的情况下显然是空的。ls -d foo1
扩展到ls *foo*
。这列出了foo1目录本身而不是其内容。进一步阅读:http://man7.org/linux/man-pages/man1/ls.1.html qazxswpoi