What happens when you type ls -l in the shell

Nic Basilio
4 min readApr 17, 2020
shell yeah!

Before we dive deeper, let me give you an overview of what ls does and show you an example of what happens when this command is typed into the terminal.

In simplest words, ls lists all the contents of a directory. Let’s take a look at this example below:

output of ls command

Adding option -l lists all the contents in long format:

output of ls -l

Background information on the shell

Shell

The shell is a program that provides an interface for a user to interact with the kernel. The shell is responsible for translating the user input into something that the kernel understands. The most common way to interact with the shell is by using the terminal.

Kernel

The kernel is the core program of your computer’s operating system. It is responsible for things such as file management, process management and memory management.

Terminal

Also known as the command line, the terminal is an interface where is a user to able to interact with the shell. It displays a command prompt (ʕ•́ᴥ•̀ʔっ in the above examples) to be followed by the user’s input.

A deeper dive

Let’s go a little deeper shall we? My project partner (Derric Donehoo) and I recently had a chance to build our own shell. Our shell is able to interact with the kernel to execute simple commands like ls, pwd and exit.

Our shell functions in 3 very easy steps:

>> It reads the command from the standard input.

Once our shell initializes, the user is greeted with a command prompt as shown below. The user input is stored in a variable for use in the following steps.

command prompt

>> It separates the command string into tokens.

Typing ls -l in the command prompt means that this user input is split into tokens (separated by a delimiter) and stored in an array of strings. In the C language, this step looks like this:

tokens[2] = {ls, -l}

The array consists of 2 elements namely ls and -l.

>> It executes the command and its arguments.

The shell tells the kernel to execute the first element of the array (in this case, ls) as a command with the rest of the elements as arguments.

The 3 steps mentioned above run in a loop until the shell is instructed to exit or until the user types Ctrl-D.

What good is the path?

Some programs have special properties or functions that make it useful to build them into the shell, and often it is required that they are built in functions because of how they behave. These are known as ‘built ins’. The shell checks first that the command is a built in, and if it is it will run this function. If not the shell moves on to check the path.

Path is a variable provided to the program through the environment. It is simply a list of the directories that the program will search to find the command. The commands definition will be stored in a file of the commands name. When commands are executed through the command line or through an exec system call, the path is searched from left to right. If the command is found on the path, it is executed as a child of the command line or program running.

Sometimes the user may want certain commands to be called by different name, or alias. When this happens, the program will expand the alias to its original name, before it searches the path for this command.

How a shell executes other programs

An integral function of the shell is how it breaks up processes. Fork-Exec is a Unix cornerstone, in which a process spawns a new ‘child’ process. The first step in this process is calling the ‘fork’ system call. This system call creates a child process that is an exact replica of the parent, meaning it inherits the file descriptors, memory allocation and environment variables of the parent process, but it has its own process ID. The next step is to give the child process a program to run, which we do by passing said program through an exec system call, often execve. The two processes can run together, but our shell is going to just run one at a time. We can achieve this by using the wait system call. Wait will make the parent process wait for the termination of the child process. All fork is doing is creating a process, and all exec is doing is executing a program. We differentiate the shells parent process and the child process using the process identifiers. While the parent waits, we can run code in the child process by using the unique process id of the child. Wait is also useful for making the child process release any resources it may be using.

--

--

Nic Basilio
0 Followers

Holberton School — Software Engineering student