为何*会将文件名放入参数向量?K&R2练习引发的技术疑问
为什么
echo *会打印所有文件名?揭秘Shell的通配符扩展机制 嘿,这个问题问到点子上了——你遇到的是**Shell通配符扩展(Globbing)**的核心机制,这是Unix/Linux类系统里Shell最基础的特性之一,咱们把它拆解开说清楚:
1. 不是echo或你的C程序处理了*,是Shell先动手了
当你在终端敲下echo *或者./your_c_program *的时候,真正处理*的不是后面的命令/程序,而是你正在使用的Shell(比如bash、zsh、sh这些):
- Shell会在执行命令之前,先扫描命令行里的通配符(比如
*),把它替换成当前目录下符合匹配规则的所有文件名(默认不包含以.开头的隐藏文件) - 替换完成后,Shell才把这些文件名作为参数传给
echo或者你的C程序 - 所以
echo只是单纯打印接收到的所有参数,你的C程序拿到的argv数组里也已经是扩展后的文件名列表,根本看不到原始的*
2. *的特殊身份:Shell通配符
*是Shell提供的通配符之一,它的作用是匹配任意长度的任意字符(除了文件名开头的.,除非你开启了Shell的dotglob选项)。类似的常用通配符还有:
?:匹配单个任意字符[abc]:匹配a、b、c中的任意一个字符[!abc]:匹配除了a、b、c之外的任意字符
这些通配符的解析都是Shell的工作,和你运行的程序完全无关——所有需要接收命令行参数的程序,都会享受到Shell提前做好的扩展处理。
3. 怎么让程序直接拿到*?
如果你不想让Shell扩展*,想让你的C程序或者echo直接收到*这个字符,只需要用引号把它括起来就行:
- 比如执行
echo "*",终端会直接输出* - 或者运行
./your_c_program "*",你的程序就能在argv里拿到原始的*参数了
补充:这个机制的由来
早期Unix系统里,通配符扩展是由echo这类命令自己实现的,但后来为了统一逻辑、减少重复代码,就把这个功能移到了Shell层面——这样所有程序都能自动支持通配符,不用各自开发一遍解析逻辑。
内容的提问来源于stack exchange,提问作者Murat Göksel
相关产品推荐
相关产品推荐

