Linux: The Operating System

October 26, 2025 | 44 min read

unixoneshot

If you are reading this, you probably interested in learning about linux. why linux? because it is the backbone of the modern internet. Everyone should know their system, As a software engineer you will cross path with linux systems more than often, so learning it does not hurt.

I tried to cover EVERYTHING (literally). if things goes off your head, just google some words. This post starts with Core OS foundation of the linux system to give you just the introduction so you don't feel lost

Lego of the Linux

There are four main components that make up the linux system.

  1. The linux kernel
  2. The GNU utils
  3. A graphical desktop environment
  4. Application Software

1. Kernel

The linux kernel is a free-and open-source for the Unix-Like Kernel, It was created by linus torvalds in 1991 and soon adopted as the kernel for the GNU Operating System.

The kernel is assigned 4 tasks:

  1. System memory management
  2. Software program management
  3. Hardware management
  4. Filesystem management

1. System memory management

Not only does the kernel manage physical memory available on the server but it can also create and mange virtual memory. Kernel can create virtual memory using the space on the hard disk known as swap space. When physical memory is full Kernel swaps the data that is not immediately needed from memory to swap space to free up some memory. When data is needed again, it would copy it back to the memory.

Virtual memory is the use of space on a Hard Disk to simulate additional main memory.

Kernel maintains each page of the memory in a table to keep track for pages that are swapped out to swap space. If a memory page has not been accessed for a period of time kernel would automatically swap that memory page out of main memory and when an application requests to access that memory, it must create space in main memory so that page can be swapped back.

The memory locations are grouped into blocks known as pages. pages allows memory used by a program to be non-contiguous.

2. Software Program Management

The Kernel first loads a Process called init process into virtual memory. As the kernel starts each additional process, it gives it a unique area in virtual memory to store the data and code that the process uses. Some Linux implementations contain a table of processes to start automatically on bootup. the popular Ubuntu Linux distribution utilize the /etc/init.d folder, which contains scripts for starting and stopping individual applications at boot time

The memory locations are grouped into blocks known as pages. pages allows memory used by a program to be non-contiguous.

On macOS, the traditional UNIX-style init process does not exist. Apple replaced it with its own system management daemon called launchd.

The scripts are started via entries under the /etc/rcX.d folders, where X is a run level.

The Linux operating system uses an init system that utilizes run levels. A run level can be used to direct the init process to run only certain types of processes, as defined in the /etc/inittabs file or the /etc/rcX.d folders.

There are five init run levels in the Linux operating system. At run level 1, only the basic system processes are started, along with one console terminal process. This is called single-user mode. Single-user mode is most often used for emergency filesystem maintenance when something is broken. Obviously, in this mode, only one person (usually the administrator) can log in to the system to manipulate data.

The standard init run level is 3. At this run level, most application software, such as network support software, is started. Another popular run level in Linux is run level 5. This is the run level where the system starts the graphical X Window software and allows you to log in using a graphical desktop window.

By changing the run level from 3 to 5, the system can change from a console-based system to an advanced, graphical X Window system.

3. Hardware Management

Any device that the Linux system must communicate with needs driver code inserted inside the kernel code. The driver code allows the kernel to pass data back and forth to the device, acting as a middle man between applications and the hardware. Two methods are used for inserting device driver code in the Linux kernel

  1. Drivers compiled in the kernel
  2. Driver modules added to the kernel

Previously, the only way to insert device driver code was to recompile the kernel. Each time you added a new device to the system, you had to recompile the kernel code. This process became even more inefficient as Linux kernels supported more hardware.

Fortunately, Linux developers devised a better method to insert driver code into the running kernel. Programmers developed the concept of kernel modules to allow you to insert driver code into a running kernel without having to recompile the kernel. Also, a kernel module could be removed from the kernel when the device was finished being used. This greatly simplified and expanded using hardware with Linux.

There are 3 classification of device files.

The Linux system identifies hardware devices as special files, called device files.

  1. Character
  2. Block
  3. Network

Character files are for devices that can only handle data one character at a time. Most types of modems and terminals are created as character files. Block files are for devices that can handle data in large blocks at a time, such as disk drives. Network file types are used for devices that use packets to send and receive data. This includes network cards and a special loopback device that allows the Linux system to communicate with itself using common network programming protocols

Linux creates special files, called nodes, for each device on the system. All communication with the device is performed through the device node. Each node has a unique number pair that identifies it to the Linux kernel. The number pair includes a major and a minor device number. Similar devices are grouped into the same major device number. The minor device number is used to identify a specific device within the major device group.

4. File Systems

Linux is flexible when it comes to filesystems. Different operating systems use different filesystems (like NTFS for Windows, HFS+ or APFS for macOS, ext4 for Linux). Unlike some OS that only understand their own filesystem, the Linux kernel is designed to handle many.

The Linux kernel interfaces with each filesystem using the Virtual File System (VFS). This provides a standard interface for the kernel to communicate with any type of filesystem. VFS caches information in memory as each filesystem is mounted and used.

2. GNU Utilities

A computer operating system needs utilities to perform standard functions, such as controlling files and programs. While Linus created the Linux system kernel, he had no system utilities to run on it. Around the same time, the GNU project developed a full set of Unix-like utilities under the open source software (OSS) philosophy.

The Core GNU Utilities

The core bundle of utilities supplied for Linux systems is called the coreutils package. The GNU coreutils package consists of three parts:

  1. Utilities for handling files
  2. Utilities for manipulating text
  3. Utilities for managing processes

The GNU/Linux Shell

The GNU/Linux shell is an interactive program that lets users run commands, manage files, and control processes. It works through a command prompt, where entered commands are interpreted and executed by the kernel.

The shell includes built-in commands (like copying or moving files) and can also start external programs. Commands can be grouped into shell scripts, allowing automation of tasks.

Multiple shells exist, each with unique features. The default is bash (the Bourne Again Shell), created by the GNU project as an improved version of the original Bourne shell.

The Linux Desktop Environment

In the early 1990s, Linux only had a text-based interface for running programs and managing files. As Windows popularized graphical user interfaces, users began expecting similar functionality. This led the open-source community to develop graphical desktop environments for Linux.

Today, Linux offers multiple desktop options.

1. The X Window software is the core element in presenting graphics. It acts as a bridge between the video card, monitor, and applications, allowing programs to create windows and render graphics.

The most common implementation is X.org, an open-source version that supports a wide range of hardware. Newer alternatives include Wayland (used by Fedora) and Mir (developed by Ubuntu).

When you first install a Linux distribution, it attempts to detect your video card and monitor, and then it creates an X Window configuration file that contains the required information. While X Window provides the foundation for graphics, it doesn't include a desktop environment. To manage files, launch programs, and interact visually, you need a desktop environment (like GNOME, KDE, etc.) running on top of X Window.

2. KDE (The K Desktop Environment) is one of the most feature-rich desktop environments available for Linux. It gives users a fully customizable graphical interface that looks and feels similar to Windows.

3. GNOME takes a different approach from KDK. it's simpler, less cluttered, and focuses on usability rather than Windows-style familiarity. It's the default desktop for many major Linux distributions like Fedora, Red Hat, and CentOS.

4. Unity was Canonical's unique spin on desktop environments, blending a modern interface with a focus cross-device consistency.

Linux Distributions

A complete Linux system package is called a distribution. There are mainly 3 type of distributions.

  1. Full core linux distribution
  2. Specialized distributions
  3. LiveCD test distributions

A core Linux distribution contains a kernel, one or more graphical desktop environments, and just about every Linux application that is available, precompiled for the kernel. It provides one-stop shopping for a complete Linux installation. For example, Fedora (A spin-off from Red Hat but designed for home use), Debian (Popular with Linux experts and commercial Linux products).

Specialized distributions are typically based on one of the main distributions but contain only a subset of applications that would make sense for a specific area of use. For example, Ubuntu (A free distribution for school and home use), CentOS (A free distribution built from the Red Hat Enterprise Linux source code). Many of the specialized Linux distributions are based on the Debian Linux distribution. They use the same installation fi les as Debian but package only a small fraction of a full-blown Debian system.

A Linux LiveCD is a bootable version of Linux that runs directly from a CD without needing to install anything on your hard drive. It allows users to explore and experience a full Linux environment safely, without making permanent changes to their system. Because the CD has limited space, it contains only a sample version of Linux, but it still includes enough tools and software to demonstrate how the system works.


The Shell

A simple shell CLI on the monitor, just like the days before graphical desktops. This mode is called the Linux console because it emulates the old days of a hard-wired console terminal and is a direct interface to the Linux system.

When the Linux system starts, it automatically creates several virtual consoles. In the old days, a computer might have had several physical terminals (screens and keyboards) connected to it, each giving access to the system. Virtual consoles simulate that setup but instead of needing multiple terminals, you can switch between several terminal sessions on a single monitor and keyboard.

A virtual console is a terminal session that runs in Linux system memory.

Each virtual console runs its own login session and shell. You can move between them using keyboard shortcuts. for example, Ctrl + Alt + F1 through Ctrl + Alt + F6 each key combination opens a different console. Typically, one of these consoles runs the graphical desktop (like GNOME or KDE), while others provide text-based command-line access.

A graphical terminal is an alternative to using the traditional virtual console. Instead of switching to a text-only screen, you can open a terminal emulator directly inside your Linux graphical desktop environment. This terminal emulator mimics a console terminal but runs in a graphical window, allowing you to execute command-line tasks while still working in the GUI.

The graphical experience in Linux is built through multiple components working together. The client (such as the desktop environment, file manager, or terminal emulator) is the application that requests graphical services. The display server (like Xserver, Wayland, or Mir) manages the display, screen, and input devices. The window manager (such as Compiz, Metacity, or Kwin) handles window borders, resizing, and movement. Finally, the widgets library (like Athena (Xaw) or X Intrinsics) provides menus and visual elements that define the desktop's appearance.

In Linux, when you log into a text-based terminal (outside the graphical interface), you might see something like:

login: user
Password:
Last login: Thu Oct 30 21:40:07 on tty2

Here, tty2 refers to virtual console 2, which you can access using the keyboard shortcut Ctrl + Alt + F2. Each virtual console has its own identifier tty1, tty2, tty3, etc.

The term tty stands for teletypewriter, a legacy term from early computing when physical teletype machines were used to interact with mainframes. Modern Linux systems use virtual ttys (software-based terminals) instead. For example, tty1 might be your login screen, tty2 a command-line session, and tty7 often runs the graphical desktop environment (like GNOME or KDE).

macOS uses pseudo-terminals like ttys000, Linux systems use virtual terminals like tty1-tty7. both are serving the same purpose of managing user sessions and terminal input/output.


The Basic Bash Shell Commands

'/etc/passwd' command

The /etc/passwd file contains a list of all the system user accounts, along with some basic configuration information about each user

nikhar:x:501:501:Nikhar Savaliya:/home/nikhar:/bin/bash

Each entry has seven data fields, with fields separated by colons. Here, nikhar is the username. x indicates that the password is stored in the /etc/shadow file for security. 501 is the user ID (UID). 501 is the group ID (GID). Nikhar Savaliya is the full name of the user. /home/nikhar is the home directory. /bin/bash is the default shell for the user.

As per this entry, when user 'nikhar' logs into the system the bash shell program automatically starts because user has /bin/bash as default shell program

The default bash prompt symbol is $. This symbol means that shell is waiting for you to fire some text.

'man' command

The man command provides access to the manual pages stored on the Linux system. For example, you can do man git to see git commands man page, or you can do man git-commit to see commit utilities man page. The bash manual is not a step-by-step guide, but instead a quick reference.

When you use the man command to view a command's manual pages, they are displayed with something called a pager. Thus, you can page through the man pages by pressing the spacebar, or you can go line by line using the Enter key. In addition, you can use the arrow keys to scroll forward and backward through the man page text (assuming that your terminal emulation package supports the arrow key functions). press the q key to quit

A pager is a utility that allows you to page through displayed text.

there are man page section areas. Each section area has an assigned number, starting at 1 and going to 9; they are listed in Table.

Section | Description
------- | --------------------------------------------------------------------------------------------------------------
1       | Executable programs or shell commands these are what you actually type in your terminal.
2       | System calls functions provided by the kernel, the raw interface between your program and the system.
3       | Library calls higher-level functions that sit on top of system calls (think `printf()` and `malloc()`).
4       | Special files everything under `/dev` and other system interfaces that act like files.
5       | File formats and conventions configuration files, syntax formats, and structural conventions.
6       | Games yes, the Unix manual has a section just for games (because of course it does).
7       | Overviews, conventions, and miscellaneous protocols, standards, and general documentation.
8       | System administration commands tools used by root or for managing the system.
9       | Kernel routines internal functions used within the kernel itself. Rarely touched unless you’re building one.

When you search for a man page by name, you might see multiple versions of it in different sections. You can list them all using: bash man -f printf or bash whatis printf .

This tells you every place the keyword appears, e.g. printf (1) for the shell command and printf (3) for the C library function.

Each section in the manual isn't just a different “type” of information, it's a different layer of the Unix system. From shell commands (Section 1) all the way down to kernel internals (Section 9), these layers form the vertical anatomy of Unix.

File System & Navigation

Linux stores files within a single directory structure, called a virtual directory. The virtual directory contains file paths from all the storage devices installed on the computer, merged into a single directory structure. The Linux virtual directory structure contains a single base directory, called the root. Directories and files beneath the root directory are listed based on the directory path used to get to them, similar to the way Windows does it.

The tricky part about the Linux virtual directory is how it incorporates each storage device. The first hard drive installed in a Linux system is called the root drive. The root drive contains the virtual directory core. Everything else builds from there.

On the root drive, Linux can use special directories as mount points.
Mount points are directories in the virtual directory where you can assign additional storage devices.
Linux causes files and directories to appear within these mount point directories, even though they are physically stored on a different drive.
Often system files are physically stored on the root drive. User files are typically stored on a separate drive or drives

Disk 1                         Disk 2
------                         ------
/
├── bin                        ├── barbara
├── etc                        ├── jessica
├── home  ------------------>  ├── katie
├── usr                        └── rich
└── var

One hard drive is associated with the root of the virtual directory (indicated by a single forward slash). Other hard drives can be mounted anywhere in the virtual directory structure. In this example, the second hard drive is mounted at the location /home, which is where the user directories are located.

The Linux filesystem structure originally evolved from the Unix file structure. In a Linux filesystem, common directory names are used for common functions. common Linux virtual top-level directory names and their content are listed in the table below:

Directory  | Description
---------- | --------------------------------------------------------------------------------------------------------------
/          | root of the virtual directory, where normally, no files are placed
/bin       | binary directory, where many GNU user-level utilities are stored
/boot      | boot directory, where boot fi les are stored
/dev       | device directory, where Linux creates device nodes
/etc       | system configuration files directory
/home      | home directory, where Linux creates user directories
/lib       | library directory, where system and application library files are stored
/media     | media directory, a common place for mount points used for removable media
/mnt       | mount directory, another common place for mount points used for removable media
/opt       | optional directory, often used to store third-party software packages and data files
/proc      | process directory, where current hardware and process information is stored
/root      | root home directory
/sbin      | system binary directory, where many system administration utilities are stored
/run       | run directory, where runtime data is held during system operation
/srv       | service directory, where local services store their fi les
/sys       | system directory, where system hardware information fi les are stored
/tmp       | temporary directory, where temporary work fi les can be created and destroyed
/usr       | user binary directory, where the bulk of GNU user-level utilities and data files are stored
/var       | variable directory, for fi les that change frequently, such as log files

When you log in to your system and reach a shell CLI prompt, your session starts in your home directory. Your home directory is a unique directory assigned to your user account. When a user account is created, the system normally assigns a unique directory for the account

'pwd' command

The pwd command displays the shell session's current directory location, which is called the present working directory.

$ pwd
=> /home/nikhar

'cd' command

The cd command changes the shell session's current directory to a different directory. You can specify either an absolute or a relative path to the new directory. the (.) symbol represents the current directory, and the (..) symbol represents the parent directory of the current directory.

$ cd ./Documents
$ pwd
=> /home/nikhar/Documents

# relative path
$ cd ..
$ pwd
=> /home/nikhar

# absolute path
$ cd /etc
$ pwd
=> /etc

'ls' command

The ls command lists the files and directories in the current directory. You can also specify a different directory to list its contents.

$ ls
=> Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos

To display hidden files along with normal files and directories, use the -a parameter. Hidden files and directories have names that start with a dot (.), such as .bashrc or .config.

$ ls -a
=> .  ..  .bashrc  .config  Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos

The -R parameter is another option the ls command can use. This parameter tells the ls command to list all subdirectories recursively.

$ ls -R
=> Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos
./Documents:
Resume.pdf  Project1  Project2
./Project1:
file1.txt  file2.txt
./Project2:
file3.txt  file4.txt

another popular parameter is -l. The -l parameter produces a long listing format, providing more information about each fi le in the directory:

$ ls -l
=> total 32
drwxr-xr-x 2 nikhar nikhar 4096 Oct 26 10:00 Desktop
drwxr-xr-x 5 nikhar nikhar 4096 Oct 26 09:50 Documents
drwxr-xr-x 3 nikhar nikhar 4096 Oct 26 09:55 Downloads
drwxr-xr-x 4 nikhar nikhar 4096 Oct 26 09:45 Music
drwxr-xr-x 6 nikhar nikhar 4096 Oct 26 09:40 Pictures

you can filter our the long listing format with hidden files using both -l and -a parameters together.

$ ls -la
=> total 40
drwxr-xr-x 8 nikhar nikhar 4096 Oct 26 10:05 .
drwxr-xr-x 3 root   root   4096 Oct 25 20:00 ..
-rw-r--r-- 1 nikhar nikhar  220 Apr  4  2018 .bash_logout

$ ls -l my_file
=> -rw-r--r-- 1 nikhar nikhar 1024 Oct 26 10:10 my_file

The ls command also recognizes standard wildcard characters and uses them to match patterns within the filter, A question mark (?) to represent one character and an asterisk (*) to represent zero or more characters.

$ ls *.txt
=> file1.txt  file2.txt  file3.txt  file4.txt

Using the asterisk and question mark in the filter is called file globbing. File globbing is the processing of pattern matching using wildcards. The wildcards are officially called metacharacter wildcards. You can use more metacharacter wildcards for file globbing than just the asterisk and question mark. You can also use brackets:

$ ls -l my_scr[ai]pt
=> -rw-rw-r-- 1 christine christine 0 May 21 13:25 my_script
=> -rw-rw-r-- 1 christine christine 0 May 21 13:25 my_scrapt

# you can specify what should not be included
# in the pattern match by using the exclamation point(!)

$ ls -l my_scr[!ai]pt
=> -rw-rw-r-- 1 christine christine 0 May 21 13:44 fell

'mkdir' command

The mkdir command creates a new directory in the current directory or at a specified path.

$ mkdir Projects
$ ls
=> Desktop  Documents  Downloads  Music  Pictures  Projects  Public  Templates  Videos

You can also create nested directories using the -p parameter. This allows you to create parent directories as needed.

$ mkdir -p Projects/2025/October
$ ls Projects
=> 2025

'touch' command

Every once in a while you run into a situation where you need to create an empty file. The touch command is a quick way to create an empty file.

$ touch myfile.txt
$ ls
=> Desktop  Documents  Downloads  Music  myfile.txt  Pictures  Public  Templates

The touch command can also be used to change the modification time. This is done without changing the file content

$ ls myfile.txt
=> -rw-rw-r-- 1 nikhar nikhar 0 May 21 14:17 test_one
$ touch myfile.txt
$ ls myfile.txt
=> -rw-rw-r-- 1 nikhar nikhar 0 May 21 14:19 test_one

'cp' command

The cp command copies files and directories from one location to another. By default, it copies files to the specified destination.

$ cp myfile.txt myfile_copy.txt
$ ls
=> Desktop  Documents  Downloads  Music  myfile.txt  myfile_copy.txt  Pictures  Public  Templates

The -R parameter is a powerful cp command option. This parameter tells the cp command to copy directories recursively, including all files and subdirectories within the specified directory.

$ cp -R Projects Projects_Backup
$ ls
=> Desktop  Documents  Downloads  Music  myfile.txt  myfile_copy.txt  Pictures  Projects  Projects_Backup  Public  Templates

# You can also use wildcard metacharacters in your cp commands:
$ cp *.txt TextFilesBackup/
$ ls TextFilesBackup
=> myfile.txt  myfile_copy.txt

Linking files

Imagine you have to manage 2 or more copies of the same files, you would have to copy and paste that file to every location when you edit that file. In linux, you can create a Link.
A Link is a special computer file that stores the refers to another file or directory by storing a path to it.
This link is just a placeholder in the directory that points to the real address of that file.

There are two types:

  1. Hard Links
  2. Soft Links
A hard link in Linux is a directory entry that directly references the same inode as the original file, meaning it points to the same underlying data on disk.
inode is a data-structure in the unix system that holds the metadata about the file. It doesn't hold the file's name or content, but it tells the system where the content lives and who owns it.

Each file or directory gets a unique inode number in the filesystem. The inode number of a file or directory is a unique identification number that the kernel assigns to each object in the filesystem. If the original file is deleted or renamed, the hard link still works because it points to the same inode (same data).

$ ls -i demo.txt
=> 16777231 16832081 -rw-r--r-- 1 nikhar staff 0 12 "Nov 10 23:26:04 2025" "Nov 10 23:26:03 2025" "Nov 10 23:26:03 2025" "Nov 10 23:25:59 2025" 4096 8 0 demo.txt

A symbolic link (aka symlink or soft link) is a special file that refers to another file or directory by storing a path to it. If the target moves or is deleted, the symlink does not automatically update. it will point to a non-existent path and is then considered broken, orphaned, dangling.

$ echo 'gm my G' > og.txt
$ ln -s og.txt symog.txt

$ ls -l
total 8
-rw-r--r--@ 1 nikhar  staff  8 10 Nov 23:43 og.txt
lrwxr-xr-x@ 1 nikhar  staff  6 10 Nov 23:53 symog.txt -> og.txt

# See that both files have different inodes here.
$ ls -i og.txt symog.txt
16835864 og.txt    16838059 symog.txt

Renaming files

In linux you don't rename files, you move them. Use mv command to move files/directories to another location or rename them.

$ ls -l
total 8
-rw-r--r--@ 1 nikhar  staff  8 10 Nov 23:43 og.txt
lrwxr-xr-x@ 1 nikhar  staff  6 10 Nov 23:53 symog.txt -> og.txt

# rename og.txt to renamed-og.txt
$ mv og.txt renamed-og.txt

$ mkdir links
$ ls -li
total 8
16842943 drwxr-xr-x@ 2 nikhar  staff  64 11 Nov 00:13 links
16835864 -rw-r--r--@ 1 nikhar  staff   8 10 Nov 23:43 renamed-og.txt
16838059 lrwxr-xr-x@ 1 nikhar  staff   6 10 Nov 23:53 symog.txt -> og.txt

$ mv symog.txt links/symog.txt

$ ls -li
total 8
16842943 drwxr-xr-x@ 3 nikhar  staff  96 11 Nov 00:14 links
16835864 -rw-r--r--@ 1 nikhar  staff   8 10 Nov 23:43 renamed-og.txt

$ cd links && ls -li
total 0
16838059 lrwxr-xr-x@ 1 nikhar  staff  6 10 Nov 23:53 symog.txt -> og.txt

Note that there were no change in the file's inode number or timestamp.

Deleting files

In linux there is no deleting, it's removing (ok i need to stop). The command is rm. The shell has no recycle bin or trashcan. After you remove a file it's gone forever. use -i parameter, it prompts you to make sure you are 100% seriously wants to remove this file.

$ ls
symog.txt

$ rm -i symog.txt
remove symog.txt? yes

Create Directory

you can create directories using mkdir command. mkdir command takes name of the directory.

$ mkdir test

$ ls -l
drwxr-xr-x@ 2 nikhar  staff  64 11 Nov 00:24 test

# use -p parameter to create nested directories as well.
# -p creates any missing parent directory provided in the path

$ mkdir -p test/nest1/nest2

$ tree test
test
└── nest1
└── nest2

3 directories, 0 files

Notice that the record for test directory starts with d. This indicates that this object is not a file it's a directory.

Deleting Directories

User can be dumb, and since there is no bin/trash in CLI, we don't want user to delete anything unknowingly. Therefor by default the rmdir command allows to delete empty directories.

$ rmdir links
rmdir: links: Directory not empty

$ ls
links          renamed-og.txt test

$ rmdir test

$ ls
links          renamed-og.txt

To fix this, you must empty the directory first, then with rmdir you can remove the directory. You can also use rm command with -r option allowing you to descend into the directory, remove the files, and then remove the directory it self. This also works if you have multiple subdirectories nested.

$ rm -r links

rm command had -r and -R option, both does the same thing, don't know why this a thing.

The rm -rf command gives no warnings and no fanfare. This is the final boss when you want to delete.

View Files

'file' command

The file command is a handy little utility to have around. It can peek inside of a file and determine just what kind of file it is

$ file renamed-og.txt
renamed-og.txt: ASCII text

$ file links
links: directory

The file command determined not only that the file contains text but also the character code format of the text file, ASCII.

'cat' command

The cat command is a handy tool for displaying all the data inside a text file.

$ cat renamed-og.txt
gm my G

$ cat -n renamed-og.txt # gives all the lines with numbers (including empty lines)
1  gm my G
2

$ cat -b renamed-og.txt # gives all the lines with text in them.
1  gm my G

$ cat -T renamed-og.txt # if you don’t want tab characters to appear (The -T parameter replaces any tabs in the text with the ^I character combination.)

there are more commands like less & more, feel free to look it up (not covering here).

you can use head & tail commands to view part of the file. For example, head -n 10 <FILE_NAME> prints first 10 lines of the file. tail -n 10 <FILE_NAME> prints the last 10 lines of the file.


Some More Advanced Shell Commands

Previously all the commands were for you to use the linux system, now we are about to see the commands that allows us to do linux system management.

Monitoring Processes

When a program runs on your system, its called a process. ps command (it is one of the most difficult commands to master btw), It can product a lot of information about the processes running on your system. It has a lot of parameters to process all the information you need. You can play around and curate the list of parameters you would need and stick with it.

$ ps
PID TTY           TIME CMD
47311 ttys001    0:00.41 -zsh
83529 ttys016    0:00.10 /bin/zsh -il
83853 ttys016    0:00.29 node /opt/homebrew/bin/pnpm dev
83867 ttys016    2:00.00 next-server (v15.5.6)
87513 ttys017    0:00.11 -/bin/zsh

By default, ps command lists the processes for the current user and running on the current shell. It shows the process id (PID), terminal (TTY) and the CPU time(TIME) that they have used.

You can use -ef parameter combo to see everything running on the system. here -e parameter shows all processes running on the system, and -f parameter shows addition fields like UID, PID, PPID etc. For even more information you can use -l parameter. this were UNIX style parameters, which were preceded with a dash(-). There are some BSD(Berkeley system distribution) style parameters. like T parameter shows the processes running on current terminal. 'r' shows only running processes. 'l' Uses the long format. 'e' shows any environment variables used by the command.

$ ps l # all the zsh processes running is because of the tmux.
UID   PID  PPID CPU PRI NI      VSZ    RSS WCHAN  STAT   TT       TIME COMMAND
501 47311 47310   0  31  0 435313312     32 -      Ss+  s001    0:00.41 -zsh
501 77653 47310   0  31  0 435313552     32 -      Ss+  s002    0:00.15 -zsh
501 68376 47310   0  31  0 435313552     32 -      Ss+  s003    0:00.24 -zsh
501 83529 75030   0  31  0 435309568   1952 -      Ss   s016    0:00.10 /bin/zsh -il
501 83853 83529   0  31  0 436264624  38624 -      S+   s016    0:00.31 node /opt/homebrew/bin/pnpm dev
501 83867 83861   0  31  0 498952336 1634288 -      S+   s016    2:32.50 next-server (v15.5.6)
501 87513 87512   0  31  0 435313920   4304 -      S    s017    0:00.23 -/bin/zsh
501 88151 47310   0  31  0 435313568     32 -      Ss+  s029    0:00.12 -zsh
501 89729 47310   0  31  0 435309600     32 -      Ss+  s036    0:00.33 -zsh
501 79901 47310   0  31  0 435314144     32 -      Ss+  s038    0:00.71 -zsh

here we have new fields like 'VSZ' (the size in KB of the process), 'RSS' (The physical memory that process has used that isn't swapped out) and 'STAT' (2 character stat code representing the state of the process). The two-character code more precisely defines exactly what's happening with the process than the single-character Unix-style output. The first character uses the same values as the Unix-style S output column, showing when a process is sleeping, running, or waiting. The second character further defines the process's status:

| Character | Description                                               |
| --------- | --------------------------------------------------------- |
| <         | The process is running at high priority.                  |
| N         | The process is running at low priority.                   |
| L         | The process has pages locked in memory.                   |
| s         | The process is a session leader.                          |
| l         | The process is multi-threaded.                            |
| +         | The process is running in the foreground.                 |

The GNU long parameters, introduced by the GNU developers were their own touch on the ps command, some of the parameters copy existing Unix-BSD style parameters while other provides new features. use man command to see all available parameters.

You can combine GNU long parameters with either Unix- or BSD-style parameters to really customize your display. One cool feature of GNU long parameters that we really like is the --forest parameter. It displays the hierarchical process information, but using ASCII characters to draw cute charts. (FYI: this does not work in macintosh).

ps command can display information only for specific point in time. If you're trying to find trends about processes that are frequently swapped in and out of memory, it's hard to do that with the ps command.

Run-time Process Monitoring

top command solves this problem. this command shows the processes like in ps command but it does in real-time.

Processes: 701 total, 4 running, 697 sleeping, 3100 threads                                                                                                                                             15:02:02
Load Avg: 6.44, 4.36, 3.03  CPU usage: 5.97% user, 5.51% sys, 88.50% idle  SharedLibs: 692M resident, 149M data, 108M linkedit. MemRegions: 0 total, 0B resident, 0B private, 1633M shared.
PhysMem: 15G used (1971M wired, 3727M compressor), 392M unused. VM: 317T vsize, 5176M framework vsize, 21061497(0) swapins, 31672968(0) swapouts. Networks: packets: 104620423/94G in, 79130082/44G out.
Disks: 109781211/1873G read, 47567114/1032G written.

PID    COMMAND      %CPU TIME     #TH   #WQ  #PORT MEM    PURG   CMPRS PGRP  PPID  STATE    BOOSTS           %CPU_ME %CPU_OTHRS UID  FAULTS     COW    MSGSENT     MSGRECV     SYSBSD      SYSMACH    CSW
388    WindowServer 47.2 26:36:11 20/1  6    5659  707M-  11M    233M  388   1     running  *0[1]            1.76839 0.32059    88   140745472+ 75558  633107328+  670899526+  1367956072+ 2147483647 591276566+
87511  ghostty      26.2 00:13.23 10    2    311   163M+  4736K  13M-  87511 1     sleeping *2+[385]         0.22650 1.69729    501  90269+     453    122458+     40280+      134654+     292678+    112531+
0      kernel_task  8.7  18:51:01 563/8 0    0     17M    0B     0B    0     0     running   0[0]            0.00000 0.00000    0    774637     318    1563106466+ 1345722562+ 0           0          2147483647
  1. first line shows the total processes in each state.
  2. second line shows the Load Avg as three numbers: the 1-minute, 5-minute, and 15-minute load averages. (The higher the values, the more load the system is experiencing). It's not uncommon for the 1-minute load value to be high for short bursts of activity. If the 15-minute load value is high, your system may be in trouble.
  3. The next line shows the system memory.
  4. the next big section shows the detailed list of the currently running processes.

By default top sorts processes based on %CPU value. press q to exit the top command.

Stopping processes

Sometimes you need to stop a process programmatically. Linux follows the Unix method of inter-process communication. In Linux, process communicate with each other using signals.
A process signal is a predefined message that processes recognize and may choose to ignore or act on.

The developers program how a process handles signals. Most well-written applications have the ability to receive and act on the standard Unix process signals. There are standard process signals that Linux recognizes. Here are some of the more common ones:

| Signal | Name  | Description                                                    |
| ------ | ----- | -------------------------------------------------------------- |
| 1      | HUP   | Hang up signal; stops the currently running process            |
| 2      | INT   | Interrupt signal; stops the currently running process          |
| 9      | KILL  | Kill signal; forcefully terminates the process immediately     |
| 15     | TERM  | Termination signal; gracefully stops the process               |
| 18     | CONT  | Continue signal; resumes a stopped process                     |
| 19     | STOP  | Stop signal; pauses the process (cannot be ignored)            |

1. 'kill' command

This is the low-level, surgical way to terminate processes. You need the PID (process ID).

$ kill <PID>   # sends SIGTERM (15)

# Force kill a process
$ kill -9 <PID>

# Kill by signal name
$ kill -SIGTERM <PID>

# See all signals
$ kill -l

2. 'killall' command

Instead of hunting for PIDs, this kills all processes matching a given name.

$ killall <process-name>

# node
$ killall node

# Kill by exact match or regex
$ killall --regexp 'python[0-9]\.[0-9]'

# Kill for specific user
$ killall -u nikhar node

# List but don't kill
$ killall -i chrome

Be Careful...

killall python, It will kill EVERY python process, including system scripts. so be careful using this command.

Mounting Disk

In order to explain mounting, i am going to explain you are a 5 years old. Imagine your dad bought you a box of gifts and put it somewhere in the house. You cannot see the gifts until you ask him, “Where is the box?” and he tells you exactly which room it is in. Once you know the room, you can go there and open the box. That moment when you learn where the box is kept is like mounting. When he says the box is no longer available, that is unmounting. The gifts never move around; you just learn which place to look in order to see them.

So, mounting means attaching a filesystem from a device such as a disk or partition to a directory so the kernel knows where to expose its contents. The directory becomes a mount point, and every path lookup under that point is redirected to the mounted filesystem. Unmounting removes that connection and restores the original directory.

In Linux, the mount command works the same way. You tell the computer where the “box” is and which “room” it should be connected to. For example, if the box is at a device path like dev/sdb1 and the room you want to use is a folder like mnt/usb, the command is,

$ mount /dev/sdb1 /mnt/usb

# type parameter defines the filesystem type under which the disk was formatted
$ mount -t vfat /dev/sdb1 /mnt/usb

# use -o parameter to add special options
$ mount -o ro /dev/sdb1 /mnt/usb
# -rw -> read-write | -ro -> read-only | user -> allow user to mount
# check=none -> skip integrity check | loop -> mount a file as if it were a disk

by default, mount command displays the list of the all the media device currently mounted on the system. The mount command provides four pieces of information:

  1. The device filename of the media
  2. The mount point in the virtual directory where the media is mounted.
  3. The filesystem type
  4. The access status of the mounted media

To manually mount a media device in the virtual directory, you must be logged in as the root user or use the sudo command to run the command as the root user. After a media device is mounted in the virtual directory, the root user has full access to the device, but access by other users is restricted. You can control who has access to the device using directory permissions.

Unmount Disk

The unmount command is simply used to disconnect a filesystem from its mount point so the system stops using it. If any program has a fi le open on a device, the system won't let you unmount it

$ umount /mnt/usb # <mount-point>
$ umount /dev/sdb1 # <device>

'df' command

df shows how much space is used and how much is free on every mounted filesystem. One popular parameter is -h, which shows the disk space in human-readable form, usually as an M for megabytes or a G for gigabytes

$ df -h
Filesystem        Size    Used   Avail Capacity iused ifree %iused  Mounted on
/dev/disk3s1s1   228Gi    16Gi    63Gi    20%    447k  666M    0%   /
devfs            213Ki   213Ki     0Bi   100%     736     0  100%   /dev
/dev/disk3s6     228Gi   2.0Gi    63Gi     4%       2  666M    0%   /System/Volumes/VM
/dev/disk3s2     228Gi    15Gi    63Gi    19%    1.8k  666M    0%   /System/Volumes/Preboot
/dev/disk3s4     228Gi   754Mi    63Gi     2%     480  666M    0%   /System/Volumes/Update

This tells you:

  • The device location of the device
  • How many 1024-byte blocks of data it can hold
  • How many 1024-byte blocks are used
  • How many 1024-byte blocks are available
  • The amount of used space as a percentage
  • The mount point where the device is mounted

'du' command

du shows how much space a folder and its contents are using(by default, current working directory). Think of df as “whole disk usage” and du as “how much space this specific folder is taking.”

$ du
$ du -h <path> # formatted size
$ du -sh <path> # if you only want the total size of the folder. (-s means 'summary only')

Working with Data Files

the command is sort. It reads lines from a file or input and sorts them in different ways.

$ sort file.txt

# Sort in reverse
$ sort -r file.txt

# Sort by number instead of treating numbers as text
$ sort -n numbers.txt

# Sort by a specific column (Assume a file like)
# john 30
# alex 25
# mira 40

# Sort by the second column (numbers):
$ sort -k2 -n file.txt

# Sort and remove duplicates
$ sort -u file.txt

# Sort a command's output
$ ls | sort

#Sort by human-readable sizes (K, M, G)
$ ls -lh | sort -h -k5

Searching for Data

The command is grep. It searches for text or patterns inside files or command output.

# Basic search in a file
$ grep "hello" file.txt

# Search in all files in the current directory
$ grep "error" *

# Search recursively in all subfolders
$ grep -r "error" /var/log

# Ignore case
$ grep -i "warning" file.txt

# Show line numbers
$ grep -n "todo" file.txt

# Match whole words only
$ grep -w "cat" file.txt

# Search using a pattern (lines starting with a number)
$ grep "^[0-9]" file.txt

# Search inside command output
$ dmesg | grep usb

Compressing Data

The common command is tar. It creates compressed archives and also extracts them.

# bzip2 (.bz2)
# Compress
$ bzip2 file.txt        # creates file.txt.bz2
# Decompress
$ bunzip2 file.txt.bz2

# compress (.Z)
# Compress
$ compress file.txt     # creates file.txt.Z
# Decompress
$ uncompress file.txt.Z

# gzip (.gz)
# Compress
$ gzip file.txt         # creates file.txt.gz
# Decompress
$ gunzip file.txt.gz

# zip (.zip)
# Compress (keeps original file unless -m is used)
$ zip archive.zip file1 file2 folder/
# Decompress
$ unzip archive.zip

Archiving Data

The common tool for archiving (collecting files into one bundle) is tar. It groups files together but does not compress them unless you add options.

# Create an archive (no compression)
$ tar -cvf archive.tar file1 file2 folder/

# Extract an archive
$ tar -xvf archive.tar

# List what's inside an archive
$ tar -tvf archive.tar

# Create a compressed archive (gzip)
$ tar -czvf archive.tar.gz folder/

# Extract a compressed archive (gzip)
$ tar -xzvf archive.tar.gz

# Create a compressed archive (bzip2)
$ tar -cjvf archive.tar.bz2 folder/

# Extract a compressed archive (bzip2)
$ tar -xjvf archive.tar.bz2

What the Hell Is a Shell?

A shell is not just a CLI. It is a complicated interactive running program.

A shell is much more than a place to type commands. It's a running program that listens to you, interprets what you say, and manages the work that follows. When you enter a command, the shell breaks it down, applies its own rules, expands things like variables and paths, then starts the actual program. It handles foreground and background jobs, tracks processes, forwards signals, and keeps your session alive. It also manages your prompt, history, and keyboard shortcuts so the whole interaction feels smooth. Calling it “just a CLI” misses the point. A shell is an interpreter plus a process manager plus an interactive environment, all working together every time you press Enter.

Parent and Child Shell Relationships

The default interactive shell started when a user logs into a virtual console terminal or starts a terminal emulator in the GUI is Parent Shell. When the /bin/bash command or the equivalent bash command is entered at the CLI prompt, a new shell program is created. This is a Child Shell. use ps command with option -f before and after entering a child shell to see the changes before and after spawning child shell.

A child shell is also called a subshell. A subshell can be created from a parent shell or from another subshell.

Looking at process lists

On a single line, you can disignate a list of commands to be run one after another. this is done by entering a command list using a semicolon (;) between commands:

$ pwd ; ls ; cd Downloads ; pwd ; ls
/home/nikhar
Desktop   Downloads   Music   Public  Videos
/home/nikhar/Downloads
favicon.ico   hello.js

In the preceding example, the commands all executed one after another with no problems. However, this is not a process list. For a command list to be considered a process list, the commands must be encased in parentheses.

$ (pwd ; ls ; cd Downloads ; pwd ; ls)
/home/nikhar
Desktop   Downloads   Music   Public  Videos
/home/nikhar/Downloads
favicon.ico   hello.js

Here, the parentheses addition may not appear to be a big difference, they do cause a very difference effect. Adding parentheses and turning the command list into a process list created a subshell to execute the commands.

A process list is a command grouping type. Another command grouping type puts the commands between curly brackets and ends the command list with a semicolon (;). The syntax is as follow { command; }. Using curly brackets for command grouping does not create a subshell as a process list does.

Understanding Shell Built-In Commands

Before understanding about built-in commands, we need to understand type of shell commands: 1) built-in 2) external.

Looking at external commands

An external command, sometimes called a filesystem command, is a program that exists outside of the bash shell. They are not built into the shell program. An external command program is typically located in /bin, /usr/bin, /sbin or /usr/sbin. For example, 'ps' command is an external command.

$ which ps
/bin/sh

Whenever an external command is executed, a child process is created. This action is termed forking. Conveniently, the external command ps displays its current parent as well as its own forked child processes (PID and PPID).

Looking at built-in commands

Built-in commands are different in that they do not need a child process to execute. They were compiled into the shell and thus are part of the shell's toolkit. For example, Both "cd" and "exit" are built-in commands.

Because built-in commands do not need to fork a child process to execute, they are faster & more efficient compared to external commands.

"history" command

list downs the commands history that user executed. upto 1000 commands are listed.

use 'history' command to see upto 1000 commands history and use '!!' to replay last command you used. or use '!2' to replay 2nd last command from history.

Command history is kept in the hidden file .bash_history (can be different for other shell like zsh)

"alias" command

The 'alias' command is another shell built-in command. A command alias allows you to create an alias name for common commands (along with their parameters) to help keep your typing to a minimum. however i don't use it nor recommand aliasing. As a developer you should be able to write whole command. why have overhead of remembering command + alias both.

# list of the active aliases
$ alias -p

# create new alias
$ alias li='ls -li'

After you define an alias value, you can use it any time in your shell, including in shell scripts. Because command aliases are built-in commands, an alias is valid only for the shell process in which it is defined.