如果我有目录结构
~/foo/foo1
~/foo/foo2
~/foo/foo3
如果我从〜/ foo中的终端发出以下命令,则输出以下命令:
ls *foo1*
返回总共0个目录ls *foo*
返回3个目录foo1,foo2和foo3 ls
返回3个目录foo1,foo2和foo3 ls -d *foo1*
返回foo1 ls | grep *foo1*
返回foo1 为什么命令1。ls *Foo1*
不返回Foo1?
答案 0 :(得分:1)
这与shell文件glob(与正则表达式有所不同)无关,该文件工作正常(请参见echo *foo*
,echo *foo1*
),并且与ls处理其参数的方式。
ls *foo1*
扩展为ls foo1
。这确实列出了目录的内容,在您的情况下,该目录显然为空。
ls -d *foo1*
扩展为ls -d foo1
。这会列出foo1目录本身而不是其内容。
ls *foo*
列出所有foo *目录的空内容。即使目录名称为空,这也会导致目录名称的输出。这些是ls仅在要列出多个目录时才创建的标头。
进一步阅读: http://tldp.org/LDP/abs/html/globbingref.html http://man7.org/linux/man-pages/man1/ls.1.html
答案 1 :(得分:0)
您真的很困惑,而且您对unix shell中的任何角色都不了解。
请仔细阅读globbing,尤其是glob(7)。它与正则表达式无关(在regex(7)中说明)。 *
在外壳通配符模式和正则表达式中的作用和含义完全不同。 (因此,您在标题中提及“正则表达式”是错误的。)
在运行任何程序(甚至是任何内置命令,例如echo
)之前,都会在外壳中发生。仔细阅读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)时在shell内完成)。
顺便说一句,由于其更好的zsh
功能(我也可以尝试auto-completion),相对于bash
,我更喜欢fish
外壳而不是ls *foo*
。我只需键入zsh
,然后按 tab 键,然后我的*foo*
交互式外壳程序立即展开zsh
并编辑命令行。如果对此扩展感到满意,那么只需按 return 键,命令行就会由我的zsh
shell解析并执行。如果该扩展不是我想要的,ls
允许我编辑命令行。
此命令扩展并非特定于ls
。由Shell启动的任何程序的参数列表都是通过Shell扩展获得的。在某些情况下,您可能使用stat(1)而不是ls(1)(并且您的外壳可能已经定义了aliases,所以您的*
可能是别名其他)。
由于外壳扩展的工作方式,我建议文件名中不要包含空格或特殊字符(例如控制字符和换行符,甚至是?
或minSdkVersion
)。但是,如果要处理名称奇怪的文件路径,可以使用quoting技术。
另请参阅Parsing Posix [S]hell上的Yann Regis-Gianas出色的FOSDEM2018演讲
PS。其他操作系统的工作方式有所不同。对于Windows(我不知道并且从没使用过),有传言说命令扩展发生在程序内部(emem)(在某些crt0中是等效的)。