What goes on under the hood when you type ‘ls -l *.c’ in the shell?

A list of shells

The short answer to “what happens if you type ‘ls -l *.c’ in a shell?” is it prints out a list in long format of every file that ends in a .c extension. But we’re not here for the short answer, let’s get the -l answer. To start, let’s break down the command into it’s constituent parts and see what makes them tick.

Let’s start with how the shell actually processes input. The first step is interpretation. Our shell receives a string via the standard input (our keyboard) through the getline() function. It then parses the string to divide it into tokens. Let’s dive a bit deeper. Tokenization is the process by which the input is divided into smaller, more manageable parts. By setting a delimiter, for example a white space, it designates everything separated by that delimiter as a separate token, which are then stored in an array of strings. In our case after this process is performed we end up with three separate tokens ‘ls’ ‘-l’ and ‘*.c’.

Now we have three separate strings and each has to undergo a further process of scrutiny. The computer first checks for aliases, in other words, it verifies if any of the tokens are a shortcut for a command. If aliases are present, we undergo the process of tokenization again until everything has been properly divided and tokenized. Now we can begin checking for built-in commands. If built-in commands are found it runs them directly, but our ‘ls’ command is not, so what next?

Now the $PATH comes into play. $PATH is an environment variable that essentially functions as a map to find where in memory all programs are stored. Our shell will search through the path until it finds ls tucked away in /usr/bin/ls. It then loads it into memory and calls the fork() system call, essentially splitting up our process into parent (the shell) and child (our ls command). Then execve is called which will execute our command with it’s -l modifier and expand our *.c command. What this means is it will compare everything it found while performing the list function and see if it matches the condition after the wildcard. It will take everything that matches our wildcard condition and print it out to the prompt, effectively giving us a long format list of every .c file in our working directory.