linux - 执行 `ls *.c` 时内部会发生什么?

标签 linux shell linux-kernel wildcard

我最近对 ​​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 通配符对我来说不是很清楚,因为它已经有一个文件列表,与模式匹配。这个列表是从哪里来的?

谢谢!

最佳答案

在调用实用程序之前,命令行上的 Shell globbing 模式由 shell 扩展。

您可以通过使用 set -x 在 shell 中启用跟踪来看到这一点:

$ 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* 的内容)。

关于linux - 执行 `ls *.c` 时内部会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50294360/

相关文章:

linux - Raspbian:从 .sh 文件启动程序

linux - bash 上的 GAMESS 配置脚本错误 : syntax error near $<

linux - 如何从 Linux 中删除 busybox?

linux - 编辑已编译的内核模块以提高兼容性

linux - 来自内核模块的用户进程的已用堆大小

python - 我可以手动 ssh2 到远程主机,但 paramiko 不能,为什么?

php - "Symbolic"链接以解决对 public_html 之外的文件夹的请求?

bash - 管道中 `$?` 的正确值是多少?

c - 如何在 OSX 上找到 Clang 文件夹?

mysql - 将 MySQL 查询重定向到 shell 脚本中的日志/文本文件并读取特定字符串的文件