linux - 当 `ls *.c` 被执行时,内部会发生什么?
问题描述
我最近对 Linux 内部非常感兴趣,目前正试图了解事情是如何工作的。
我知道当我打字的时候ls
opendir()
- 函数被调用;readdir()
- 为目录数据存储中的每个目录条目调用的函数;stat()
- 如果需要,可以调用函数来获取有关文件的其他信息。
如果我遗漏了什么或有什么不对,请纠正我。
对我来说神秘的部分是文件名扩展(globbing)。
我比较了输出strace ls
open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
getdents(3, /* 14 entries */, 32768) = 440
getdents(3, /* 0 entries */, 32768) = 0
close(3) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
write(1, "2q.c ds.c fglob fnoglob\n", 272q.c ds.c fglob fnoglob
和strace ls *.c
,
stat("2q.c", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("2q.c", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
stat("ds.c", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("ds.c", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
write(1, "2q.c ds.c\n", 112q.c ds.c
) = 11
并且根据我有限的知识可以看出,在第一种情况下,它的行为确实符合我的预期open, stat
,然后是getdents
.
但是后一个,shell globbing 我不清楚,因为它已经有一个与模式匹配的文件列表。这个名单是从哪里来的?
谢谢!
解决方案
在调用实用程序之前,Shell 会扩展命令行上的 Shell 通配模式。
您可以通过在 shell 中启用跟踪来看到这一点set -x
:
$ set -x
$ ls -l f*
+ ls -l file1 file2 file3
-rw-r--r-- 1 kk wheel 0 May 11 16:49 file1
-rw-r--r-- 1 kk wheel 0 May 11 16:49 file2
-rw-r--r-- 1 kk wheel 0 May 11 16:49 file3
如您所见,shell 告诉您它调用了什么命令(在+
提示符处),并且此时它已经在命令行上扩展了模式。
该ls
命令不执行文件名通配。事实上,如果你单引用 globbing 模式来保护它不受 shell 的影响,ls
肯定会感到困惑:
$ ls -l 'f*'
+ ls -l f*
ls: f*: No such file or directory
(除非在当前目录中确实有一些东西f*
,当然)。
推荐阅读
- java - 检索数据未出现在 ListView 的片段中
- python - 比较不同数据框中的 2 列
- c - 使用事件标志阻塞任务会停止程序
- javascript - 使用函数参数声明 req.body.parameter
- algorithm - 以 n 为根的二叉搜索树
- django - django boto3: NoCredentialsError -- Ubale 来定位凭据
- laravel - 如何将 example.com 和 example.com/anything 重定向到 example.com/blog
- javascript - paypal:如何获取订单 ID 并传递到交易详情页面
- r - R中按组的代码序列:组内的重复值
- progressive-web-apps - 用户单击链接时如何打开 Windows PWA 独立应用程序?