akmal
akmal

Reputation: 665

What happens internally when `ls *.c` is executed?

I've got very interested in Linux internals recently, and currently trying to understand how things work.

I knew that when I type ls

Please correct me if I'm missing something or if it's wrong.

The part which is mystery to me is filename expansion(globbing).

I've compared the output of 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

and 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

and from my limited knowledge can tell that in the first case, it indeed behaves as I expected open, stat followed by getdents.

But the later one, with shell globbing isn't clear to me, because it there's already a list of files, which match the pattern. Where does this list came from?

Thanks!

Upvotes: 1

Views: 274

Answers (1)

Kusalananda
Kusalananda

Reputation: 15633

Shell globbing patterns on the command line are expanded by the shell before the utility is invoked.

You can see this by enabling tracing in the shell with 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

As you can see, the shell tells you what command it invokes (at the + prompt), and at that point it has already expanded the pattern on the command line.

The ls command does not do filename globbing. In fact, if you single quote the globbing pattern to protect it from the shell, ls is bound to be confused:

$ ls -l 'f*'
+ ls -l f*
ls: f*: No such file or directory

(unless there's actually something in the current directory called f* of course).

Upvotes: 5

Related Questions