What happens when ‘ls -l’ is typed into your Terminal?

Let’s try to break this down, step by step. 👩‍💻

When the input of ‘ls’ is typed, a great deal happens beneath the fingers of our laptops. First on a small scale, the computer has to register the fact that these keystrokes are even valid, printable characters. A series of checking and reading in the scancode interrupts the signal within the ‘l’ and the ’s’ and the characters are validated through a keymap. This is sent to the STDIN and ready to print.

Flowchart of finding the command

Now what. The input is processed through getline, where the stream is read and the address of the buffer containing the string is stored in a *lineptr. This line is then sent into strtok, where it is parsed into a series of tokens. This is done by using delim, or deliminators to find the area between the tokens. Each call with strtok will return a pointer to a null-terminated string containing the next token in the input. The computer then decides if there is a builtin command along the string or if there is a command found in the PATH. Commands along the PATH are deliminated using “:” between possible commands.

Once a command is found, the information associated to the command along the PATH helps dictate what to do with the given input. This makes it easier to handle these command calls in the shell that are really more of a command found in the kernel of the computer. Now that the information for ‘ls’ is found, the contents of the current working directory are listed across the terminal window. This is done by using the system call fork. While the original parent process occurs, a duplicate child process is receiving and outputting information, all while ensuring that the parent process remains running in the background.

Expanded version of forking side of flowchart

Once fork is called, the parent suspends all processes and waits for information from the child process. The child process will need the command execve shortly after forking to execute the program at hand. Once execve completes, the information is received by the parent, the environment is inherited, and is sent to standard output. After this, the original prompt appears for the user. One thing to be mindful of is what process the program is executing on. In order to be certain, the child process will return with a 0 and the parent will return with a 1.

Without any arguments, ‘ls’ builds a short, often color coded list of all of the files and directories and displays them according to the size of your terminal window.

But what about when you add ‘-l’ to the end of that command?

1. Permissions 2. Hard links 3. Owner 4. Group 5. Size 6–7. Date of modification 8. Time of modification 9. Name (Example output of the ‘ls -l’ command)

Those same keystrokes are again validated through the scancode and the signal is interrupted within the ‘-‘ and again with the ‘l’ and are again sent through the keymap and printed along with the previous ‘ls’ command through STDIN. This is parsed through the PATH and because of the use of the keystroke ‘-‘ it is confirmed that the following character is an argument for the previous command, so it executes and then frees the memory previously allocated.

When the computer receives various arguments to the information provided by the ‘ls’ command, the output can be quite vast. With the ‘a’ arguments, all of the hidden files marked with a ‘.’ before the filename are included in the simple listing of the names of the files and directories. When given ‘d’ as an argument, the information printed is only the names of the directories in the current working directory, or ‘CWD’ for the terminal.

The argument gets a little more complex when ‘l’ is received. The PATH receives this argument and parses the information into a long listing format. This is a predetermined output of the following information.

Sample of (1) file and directory permissions showing the (2) owner, (3) group, and (4) user.

First, permissions on the file or directory are displayed, denoting a ‘-‘ for file, a ‘c’ for a character special file, and ‘d’ for directory. The permissions are denoted by the letters ‘r’ for permission to read, ‘w’ for permission to write, and ‘x’ for permission to execute. If the owner, group, or other users do not have a certain permission, a ‘-‘ will be displayed.

Snippet from the above example output

The next thing displayed on the line is the number of linked hard-links. This means that there is a hard link within the current working directory. This can affect other files since hard links are really dependent on their origin for the link. For a little more information on that, it is recommended to read up on hard links versus soft links. Their understanding is quite vital to efficient systems.

After that information is parsed, the owner and group of the file or directory is received, followed by the size, date of modification or creation date and time, and lastly the name of the file or directory. This specific order and information can change depending on a few different things, but often you’ll find that if you keep your files clean and organized, the displayed output is helpful and concise. If there is ever any curiosities about the ‘ls’ command, the manual page (linked above) is quite rich with information on the behavior of the function and arguments.

Expanded version of builtin side of flowchart

But what about if it’s a builtin? The name is checked along a document to check for the information coded in the shell for that command. Once found inside the shell, the arguments get executed and the output is displayed for the user. After that, the information is again freed to make sure no memory leaks are found and the original prompt returns. For better understanding, the shell has its own manual page that although dense, has very useful information and guidance.


— — Article written on behalf of the Kati²(e) Simple Shell Project — —

— —by Kati Fredlund & Kathleen McKiernan for Holberton School — —

Cosmetologist to Coder — Holberton School New Haven