You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

执行`ls *.c`时系统内部流程及shell globbing疑问解析

关于Linux文件名扩展(Globbing)的解惑

嘿,这个问题问得特别到位——很多刚深挖Linux命令行机制的朋友都会在这一步踩坑!先给你吃颗定心丸:你之前对ls核心调用的理解完全正确:当ls没有指定具体文件时,确实会通过opendir()readdir()遍历目录,必要时调用stat()获取文件元信息。

而你困惑的strace ls *.cstrace ls的差异,核心原因只有一个:文件名扩展(globbing)是你的shell(比如bash、zsh这类交互式shell)提前完成的,根本轮不到ls来处理

具体拆解两种场景:

  • 当你执行strace ls时,shell直接把ls作为命令传递给内核启动,此时ls没有收到任何文件名参数,所以它会默认遍历当前工作目录,这就是你看到opendir()getdents()等系统调用的原因。
  • 当你执行strace ls *.c时,shell在启动ls之前,会先识别到*.c这个通配符:它会主动遍历当前目录,找出所有以.c结尾的文件,把*.c替换成这些匹配到的文件名列表(比如a.c b.c test.c),然后再把这个完整的文件名列表作为参数传给ls

换句话说,ls拿到的已经是现成的、匹配好的文件名,它根本不需要自己去做通配符匹配,自然也就不会有相关的系统调用了。

你可以用两个小实验验证这个逻辑:

  • 执行echo *.c,会直接输出当前目录下所有.c文件的名称——这就是shell提前处理通配符的直接证据。
  • 执行strace ls '*.c'(注意用单引号把通配符括起来),此时shell会把*.c当成普通字符串传递给lsls就会尝试查找名为*.c的文件,你会在strace里看到它调用stat("*.c", ...)的失败记录,同时终端会提示ls: cannot access '*.c': No such file or directory

内容的提问来源于stack exchange,提问作者akmal

火山引擎 最新活动