Saril Sudhakaran
Saril Sudhakaran

Reputation: 1129

How shell glob expansion works as in ls -l *?

How is shell expanding the '*' as in

ls -l *

Is there any system calls happening behind the scene to read all the file in the directory ? I tried strace but not showing any system calls specific to globbing

Upvotes: 2

Views: 1026

Answers (3)

xhienne
xhienne

Reputation: 6144

How is shell expanding the * as in ls -l *

When meeting a globing pattern like *, the shell reads all the directory entries and compare them one by one with the pattern.

A quick glance at the source code tells me this is probably done in glob.c, especially in the glob_vector() function.

Is there any system calls happening behind the scene to read all the file in the directory ?

Of course, you cannot read the content of a directory without the help of the kernel.

That said, system calls are low-level, so don't expect to find any call to opendir() and readdir() which are libc calls. Rather, you will find calls to open() and getdents()/getdents64() instead.

I tried strace but not showing any system calls specific to globbing

strace is NOT the right tool for that. This is not your kernel that is doing globing, this is your shell, possibly with the help of libc functions, therefore there is no system call involved (except from the above-mentioned low-level calls to read the directory content).

If you want to trace calls to library functions like opendir(), readdir(), glob(), strcmp(),... you MUST use ltrace:

ltrace bash -c 'ls *'

That said, Bash has its own globing system, more advanced than the basic one specified by the POSIX standard, so it won't rely on library functions like glob() or fnmatch(). Don't expect to see calls to them in ltrace output.

If your aim is to use globbing in your own application and study how it is done, you may want to have a look at glob() which is simpler than Bash's globbing (FYI, I recently posted an example of use here).

Upvotes: 2

Socowi
Socowi

Reputation: 27360

The glob is expanded by bash, not by ls. When you run strace ls * only the ls is traced, but the glob expands before ls or even strace runs so you won't see the system calls of it in the trace.

To trace the expansion of a glob use strace bash -c 'echo *'. This will also include system calls from the shell startup. To show only the system calls done for echo * you can filter the results with ...

strace bash -c '[ -e startglob ]; echo *; [ -e endglob ]' 2>&1 |
sed -n '/"startglob"/,/"endglob"/p'

Upvotes: 4

Read glob(7). Globbing would use several syscalls(2): access(2), stat(2) opendir(3), readdir(3) (which uses getdents(2)...) closedir(3). See also nftw(3).

And GNU bash is (like GNU libc and the Linux kernel) free software, you can download its source code and study it, compile it and improve it.

You can use strace(1) or gdb(1) to understand how GNU bash (or any other Linux application) works.

Of course, globbing is done by the shell (before fork(2) and execve(2)...), not by the /bin/ls process

Upvotes: 2

Related Questions