Bash Basics Tutorial: Foundational Skills for the Command Line
- Apr 19, 2025
- 17 min read
Updated: May 27
Imagine being able to control your entire operating system with just your keyboard. No mouse, no menus—just you, your terminal, and absolute control over your files, applications, and system processes. That’s the power of Bash, and it’s why it’s a skill worth learning.
In this guide, we’re going to break down the basics of Bash—the Bourne Again Shell—so you can start using the command line like a pro. Whether you’re new to programming, exploring Linux for the first time, or looking to automate tasks on your system, understanding Bash is an essential stepping stone.

What is Bash - The Bourne Again Shell?
Bash, short for Bourne Again Shell, is one of the most widely used command-line interpreters in Unix-like operating systems. It acts as both a shell and a scripting language, allowing users to interact with the operating system using text-based commands instead of a graphical interface.
Originally developed as a free and enhanced replacement for the older Bourne Shell (sh), Bash combines powerful scripting capabilities with user-friendly command-line features. It is now the default shell on many Linux distributions and is also commonly available on macOS and other Unix-based systems.
At its core, Bash serves as a bridge between the user and the operating system kernel. When you type a command like navigating directories, creating files, or running programs, Bash interprets that input and communicates with the system to execute the requested task. This makes it an essential tool for developers, system administrators, and DevOps engineers who rely on speed and automation.
One of the key strengths of Bash is its support for scripting. Instead of running commands one by one, users can write a sequence of instructions in a .sh file and execute it as a script. This allows automation of repetitive tasks such as backups, deployments, system monitoring, and file processing.
Beyond basic command execution, Bash also provides features like variables, loops, conditional statements, and functions, making it a fully capable programming environment. This is why it is often used not just for simple terminal commands, but also for building powerful automation workflows.
In short, Bash is more than just a terminal interface. It is a fundamental tool for controlling and automating systems efficiently, making it a core skill in Linux administration and software development environments.
Login Shell vs Non-Login Shell: Overview
To understand how Bash behaves in different situations, it helps to look at two important dimensions: login vs non-login shells and interactive vs non-interactive shells. These two concepts define how your shell session starts and which configuration files get loaded. Among them, the distinction between login and non-login shells plays a key role in how your environment is initialized.
What is a Login Shell?
A login shell is created when a user begins a fresh session in the system. It represents the point where you first enter the operating environment and authenticate yourself. This can happen in several ways, such as logging into a server through SSH, accessing a system via a text-based console, or starting a terminal session that explicitly launches Bash in login mode using a command like bash --login. In some graphical environments, the session manager may also start a login shell in the background.
Since a login shell is responsible for setting up the full user environment, it performs a complete initialization process. It loads system-wide settings first, then applies user-specific configurations. This ensures that environment variables, paths, and system behavior are properly defined before any commands are executed.
During this startup process, Bash reads a specific set of configuration files in a defined order. It begins with /etc/profile, which contains system-wide settings that apply to all users. After that, it looks for user-level configuration files. It first checks ~/.bash_profile, and if that file is not found, it moves to ~/.bash_login. If neither of those exists, it finally falls back to ~/.profile.
These files are commonly used to configure environment variables such as PATH, define system-wide behaviors, and execute commands that should run only once when the user logs in. Because they are executed only during login, they are ideal for initializing long-term environment settings rather than repetitive tasks.
What is an Interactive Shell?
An interactive shell is a Bash session that is directly connected to a terminal, allowing you to type commands and receive immediate output in real time. It is the most familiar way most users interact with Bash, typically through terminal applications like GNOME Terminal, iTerm2, or Windows Terminal with a Bash environment installed.
In an interactive shell, the system presents a prompt and waits for user input. Every command you type is executed instantly, and the results are displayed right away in the same terminal window. This makes it ideal for exploration, testing commands, and day-to-day system usage.
One of the most useful aspects of an interactive shell is the user experience it provides. Features like command history allow you to reuse previously executed commands, while autocompletion helps speed up typing by suggesting files, directories, and command options. These small conveniences make working in the terminal much more efficient and productive.
When it comes to configuration, an interactive non-login shell typically relies on the ~/.bashrc file. This file is where most user-specific shell customizations are stored. It is commonly used to define aliases, customize the command prompt, enable shell options, and set up interactive behaviors that improve usability during terminal sessions.
Because .bashrc is loaded every time a new interactive shell is opened, it ensures that your preferred environment is consistently applied across all terminal sessions.
Here's a simple way to think about it:
Shell Type | Started By | Reads Config File(s) | Has Prompt? |
Login Shell | SSH, console login, bash --login | /etc/profile, ~/.bash_profile | Yes |
Interactive Shell | Terminal window, bash manually | ~/.bashrc | Yes |
Opening the Terminal
Before you can start using Bash, you need to open a terminal. The terminal is the application that allows you to directly communicate with your operating system using text-based commands. Instead of clicking through folders and menus, you type instructions that the system executes immediately.
On Linux systems, the terminal is usually available by default. A quick way to open it is by
using the keyboard shortcut:
Ctrl + Alt + TYou can also open it by searching for “Terminal” in your applications menu. Most Linux distributions include terminal emulators such as GNOME Terminal or Konsole, which provide a full Bash environment.
On macOS, the terminal is also pre-installed. You can open it using Spotlight Search by pressing:
Cmd + SpaceThen type:
Terminaland press Enter. This launches the macOS Terminal application, which runs a Bash-compatible shell (or Zsh by default in newer versions, which still supports Bash commands).
On Windows, Bash is not available natively in older setups, but you can still use it through tools like Windows Subsystem for Linux (WSL) or Git Bash. WSL provides a full Linux environment inside Windows, while Git Bash offers a lightweight Bash-like terminal for running common commands.
Once the terminal opens, you will see a line similar to this:
username@computer:~$This is called the shell prompt. It indicates that Bash is ready to accept your input. It usually displays your username, system name, and current working directory. The ~ symbol represents your home directory, which is your default starting location.
Understanding Basic Command Structure
Every command in Bash follows a consistent and predictable pattern. Understanding this structure is essential because almost every Linux command is built the same way.
The general syntax looks like this:
command [options] [arguments]Here, the command is the instruction you want the system to perform. The options (also called flags) modify how that command behaves. The arguments specify the target files, directories, or values that the command should operate on.
For example, consider the following command:
ls -la /home/userIn this case, ls is the command used to list files and directories. The -l option tells Bash to display the output in a detailed “long format,” showing file permissions, ownership, size, and modification time. The -a option ensures that hidden files (those starting with a dot) are included in the output. Finally, /home/user is the argument, which tells the command which directory to list.
Once you become comfortable with this structure, you’ll notice that most Linux commands follow the same logic. This consistency is one of the reasons Bash is so powerful and easy to learn over time.
Navigating the Filesystem
One of the first practical skills in Bash is learning how to move around the filesystem. In Linux and Unix-like systems, everything is organized in a hierarchical directory structure, similar to a tree. Bash provides simple commands to explore and navigate this structure efficiently.
To find out your current location in the system, you use the following command:
pwdThis stands for print working directory. When executed, it displays the full path of the directory you are currently working in. This is especially useful when you are navigating between multiple folders and need to confirm your location.
To move from one directory to another, you use the cd command, which stands for change directory:
cd /path/to/folderThis command tells Bash to switch your current working directory to the specified path. If the path exists and you have permission, you will instantly move into that directory.
Bash also provides a few shortcuts that make navigation faster and more intuitive. For example, if you want to move one level up in the directory structure (to the parent folder), you can use:
cd ..If you want to quickly return to your home directory, which is your personal workspace, you can use either:
cd ~or simply:
cdBoth commands will take you back to your home directory regardless of where you are in the filesystem.
To view the contents of a directory, you use the ls command:
lsThis lists all visible files and folders in the current directory. However, the real power of ls comes from its options.
For example, to get a more detailed view of files, including permissions, ownership, file size, and modification date, you can use:
ls -lTo include hidden files (which are typically configuration files starting with a dot), you can use:
ls -aA very commonly used combination is:
ls -laThis provides a complete view of all files, both visible and hidden, in a detailed format. It is one of the most frequently used commands when working in Linux environments because it gives a full snapshot of the directory contents.
Creating and Managing Files and Folders
One of the most practical uses of Bash is working with files and directories. Whether you are organizing projects, managing datasets, or handling system files, Bash gives you quick and direct control over the filesystem without needing a graphical interface.
To begin with, you can create a new empty file using the touch command. This is often used to quickly generate placeholder files or update timestamps of existing ones.
touch filename.txtIf the file does not exist, it will be created instantly. If it already exists, Bash simply updates its modification time without changing its content.
Creating directories is just as simple. You can use the mkdir command to create a new folder in your current location:
mkdir foldernameThis is commonly used when setting up project structures or organizing files into separate sections.
Sometimes, you may need to create multiple nested directories at once, even if parent folders do not already exist. In such cases, the -p option becomes useful:
mkdir -p path/to/new/folderThis command ensures that all missing parent directories are created automatically, saving you from creating each level manually.
Moving, Copying, and Deleting Files
Once files and folders are created, managing them efficiently becomes important. Bash provides simple yet powerful commands for moving, copying, renaming, and deleting items.
To rename or move a file, you use the mv command. Interestingly, the same command handles both operations depending on how it is used.
mv oldname.txt newname.txtThis renames the file from oldname.txt to newname.txt. If you provide a different path instead, it will move the file to another directory instead of renaming it.
To create a duplicate of a file, the cp command is used:
cp original.txt copy.txtThis creates an exact copy of the original file while keeping both versions intact.
Deleting files and directories is done using the rm command. To remove a single file, you can use:
rm filename.txtTo remove a directory and everything inside it, the recursive option -r is used:
rm -r foldernameThis command is powerful and should be used carefully because it permanently deletes files and folders without moving them to a trash or recovery bin. Once removed, the data is usually not recoverable through standard commands.
Viewing and Editing Files
After creating files, you often need to view or modify their contents. Bash provides several tools for reading files depending on their size and purpose.
To display the entire content of a file directly in the terminal, you can use:
cat filename.txtThis works well for small files, but for larger files it can become difficult to read because everything is printed at once.
For better navigation through long files, the less command is commonly used. It allows you to scroll up and down through the file without overwhelming the screen:
less filename.txtIf you only need to quickly inspect the beginning or end of a file, Bash provides two very useful commands:
To view the first few lines:
head filename.txtTo view the last few lines:
tail filename.txtA particularly powerful variation of tail is used for real-time monitoring. This is especially useful for logs and continuously updating files:
tail -f log.txtThis command keeps the file open and continuously displays new content as it is added, making it extremely useful for debugging and system monitoring.
When it comes to editing files directly from the terminal, Bash supports several text editors. A simple and beginner-friendly option is nano, which provides an easy interface for writing and modifying files:
nano filename.txtFor more advanced users, editors like vim offer powerful features and deep customization, although they come with a steeper learning curve.
Understanding File Permissions
One of the most important security features in Linux is its file permission system. Every file and directory has a set of permissions that determines who can access it and what actions they are allowed to perform.
These permissions help protect sensitive data, prevent unauthorized modifications, and control how programs and scripts are executed.
You can view file permissions using the ls -l command:
ls -lThe output may look something like this:
-rwxr-xr--At first glance, this sequence of characters may seem confusing, but it contains valuable information about who can access the file and what they can do with it.
The first character indicates the file type. A dash (-) represents a regular file, while a d indicates a directory. The remaining nine characters are divided into three groups of three and represent permissions for the file owner, the group, and everyone else on the system.
-rwxr-xr--
│││ │││ │││
│││ │││ └┴┴─ Others
│││ └┴┴───── Group
└┴┴───────── User (Owner)Linux permissions are based on three basic actions:
Permission | Meaning |
r | Read |
w | Write |
x | Execute |
The read permission allows a user to view the contents of a file. The write permission allows modifications such as editing or deleting a file. The execute permission allows a file to be run as a program or script.
Permissions are assigned to three categories of users. The user (u) is the owner of the file, usually the person who created it. The group (g) consists of users who belong to the file's assigned group, allowing teams to share resources.
Others (o) refers to everyone else on the system who is neither the owner nor a member of the group. Looking again at the permission string:
-rwxr-xr--The owner has rwx, meaning full read, write, and execute access. Members of the group have r-x, which allows them to read and execute the file but not modify it. Everyone else has r--, meaning they can only read the file.
To modify permissions, Linux provides the chmod command. One common use case is making a shell script executable:
chmod +x script.shThis adds execute permission to the file, allowing it to be run directly from the terminal:
./script.shIn addition to symbolic notation (rwxr-xr-x), Linux also supports a numeric representation of permissions known as octal notation. Each permission is assigned a value:
Permission | Value |
Read (r) | 4 |
Write (w) | 2 |
Execute (x) | 1 |
The values are added together to determine the permission level for each user category. For example, rwx equals 7 (4 + 2 + 1), rw- equals 6 (4 + 2), and r-x equals 5 (4 + 1).
This allows permissions to be expressed as three digits, representing the user, group, and others. A very common permission setting for regular files is:
chmod 644 file.txtThis produces:
User → rw-Group → r--Others → r--The owner can read and modify the file, while everyone else can only view it. This is the standard setting for many text files and configuration files.
Executable scripts often use:
chmod 755 script.shThis translates to:
User → rwxGroup → r-xOthers → r-xThe owner can edit and execute the script, while other users can run it but cannot modify it. This is one of the most common permission settings for Bash scripts and applications.
For highly sensitive files, you may want to restrict access completely:
chmod 700 secrets.txtThis grants full permissions only to the owner while denying all access to group members and other users.
At the opposite end of the spectrum is:
chmod 777 file.txtThis grants read, write, and execute permissions to everyone on the system. Although convenient in some development environments, it is generally discouraged because it creates significant security risks by allowing any user to modify the file.
Understanding file permissions is an essential Linux skill. They form the foundation of system security and determine who can view, modify, or execute files. By learning how to read permission strings and use commands like chmod, you gain much greater control over your files, scripts, and overall system environment.
Pipes, Redirection, and Filters
One of the reasons Bash is so powerful is its ability to connect commands together and manipulate data directly from the command line. Instead of performing a single task at a time, you can combine multiple commands to create efficient workflows for processing files, searching data, generating reports, and automating repetitive tasks.
A key concept in Bash is redirection, which allows you to control where command input comes from and where output is sent. By default, most commands display their results in the terminal window. However, you can redirect that output to a file for later use.
To save the output of a command to a file, use the > operator:
ls > files.txtThis command runs ls and writes the results to files.txt. If the file already exists, its contents will be overwritten.
If you want to preserve the existing contents and add new output to the end of the file, use the >> operator instead:
ls >> files.txtThis appends the output rather than replacing the file.
Redirection can also work in the opposite direction. Instead of providing input through the keyboard, you can read input from a file using the < operator:
cat < files.txtIn this example, the contents of files.txt are supplied as input to the cat command. While many commands can read files directly, input redirection becomes particularly useful when working with programs that expect data from standard input.
Another powerful feature of Bash is the pipe operator (|). A pipe takes the output of one command and immediately sends it as input to another command. This allows you to chain multiple commands together without creating temporary files.
For example:
ls -l | grep ".txt"Here, the ls -l command generates a detailed list of files and directories. Instead of displaying the entire output, the pipe sends it to grep, which filters the results and displays only lines containing .txt.
This ability to connect commands is one of the defining features of Unix-like systems and enables highly efficient text processing.
Bash also provides a collection of specialized commands known as filters. These commands read input, process it in some way, and then produce modified output. Filters become especially useful when combined with pipes.
The grep command searches for specific text patterns within input data:
grep "error" logfile.txtThis command displays only the lines containing the word "error".
The sort command arranges lines in alphabetical or numerical order:
sort names.txtThis is useful when organizing large datasets or preparing data for further processing.
The uniq command removes duplicate adjacent lines from input:
uniq names.txtIt is often combined with sort to identify unique values within a file.
To count lines, words, or characters, Bash provides the wc (word count) command. For example:
wc -l file.txtThis counts the number of lines in the file.
The real power of Bash emerges when these commands are combined. For example, suppose you want to count the number of unique entries in a file:
sort names.txt | uniq | wc -lIn this command, the file contents are first sorted, then duplicate entries are removed, and finally the remaining lines are counted. Each command performs a specific task, and the pipe operator connects them into a single workflow.
By mastering redirection, pipes, and filters, you gain the ability to process large amounts of data efficiently from the command line. These tools form the foundation of many Bash scripts and are essential skills for system administration, software development, data processing, and automation.
Keyboard Shortcuts and History Navigation
As you spend more time working in Bash, you'll quickly discover that constantly retyping commands can become tedious. Fortunately, Bash provides a variety of keyboard shortcuts and history features that make command-line navigation much faster and more efficient.
One of the most commonly used shortcuts is Ctrl + A, which instantly moves the cursor to the beginning of the current command line. This is particularly useful when editing long commands and needing to make changes near the start.
Ctrl + ASimilarly, Ctrl + E moves the cursor directly to the end of the command line.
Ctrl + EWhen a command is taking too long to execute or you've accidentally started the wrong process, you can terminate it using:
Ctrl + CThis sends an interrupt signal to the running process and returns you to the command prompt.
One of the most powerful shortcuts in Bash is reverse history search. Pressing:
Ctrl + Rallows you to search through previously executed commands. As you begin typing, Bash automatically searches your command history for matching entries. This can save significant time when working with lengthy commands that you don't want to type again.
Bash also maintains a history of commands executed during previous sessions. To view your command history, use:
historyThe output displays a numbered list of commands that you have previously executed.
For example:
100 ls -la101 cd projects102 python app.py103 git statusYou can quickly rerun the most recent command using:
!!If you want to execute a specific command from history, use its history number:
!102This command reruns the entry numbered 102 from your history list.
These shortcuts and history features can dramatically improve productivity, especially when working extensively in the terminal.
Writing and Running Bash Scripts
While Bash is excellent for executing individual commands, its real power comes from scripting. A Bash script is simply a text file containing a sequence of commands that Bash executes automatically. Scripts allow you to automate repetitive tasks, reduce manual effort, and create reusable workflows.
To create your first Bash script, open a new file using a text editor such as Nano:
nano myscript.shInside the file, add the following content:
#!/bin/bashecho "Hello from Bash!"The first line, known as the shebang, tells the operating system which interpreter should execute the script. In this case, /bin/bash specifies that the Bash shell should be used.
After saving the file, you must grant execute permission before it can be run:
chmod +x myscript.shYou can then execute the script using:
./myscript.shThe output will be:
Hello from Bash!Although this example is simple, Bash scripts can automate tasks such as file backups, log monitoring, software installation, system maintenance, data processing, and application deployment.
Control Structures in Bash
Like traditional programming languages, Bash provides control structures that allow scripts to make decisions and repeat actions. These features make it possible to create intelligent automation rather than simply executing commands sequentially.
One of the most common control structures is the if statement, which allows a script to execute different commands based on a condition.
For example:
if [ "$name" == "Alice" ]; then
echo "Welcome, Alice!"
else
echo "Hello, stranger."
fiIn this script, Bash checks the value stored in the variable name. If the value is "Alice", it displays a personalized welcome message. Otherwise, it displays an alternative greeting.
Another powerful control structure is the loop, which repeats a block of commands multiple times.
Consider the following example:
for file in *.txt
do
echo "Found file: $file"
doneThis loop scans the current directory for all files ending in .txt and prints their names one by one.
Loops are particularly useful for tasks such as processing batches of files, generating reports, performing backups, and automating repetitive administrative operations.
By combining conditionals and loops, Bash scripts can handle surprisingly sophisticated workflows.
Using Variables in Bash
Variables are one of the fundamental building blocks of Bash scripting. They allow you to store information and reuse it throughout your commands and scripts.
Creating a variable is straightforward:
name="Alice"Notice that there are no spaces around the equals sign. In Bash, spaces would change the meaning of the command and cause an error.
To access the value stored in a variable, prefix its name with a dollar sign ($):
echo $nameOutput:
AliceVariables make scripts more flexible because values can be stored once and referenced many times.
In addition to user-defined variables, Bash provides numerous environment variables that store information about the current session and operating system.
For example:
echo $HOMEThis displays the path to your home directory.
Another commonly used variable is:
echo $PATHThe PATH variable contains a list of directories that Bash searches when locating executable programs.
You can also create your own environment variables using the export command:
export MY_VAR="value"Once exported, the variable becomes available to child processes and programs launched from the current shell session.
Variables play a critical role in Bash scripting because they make scripts reusable, configurable, and easier to maintain. Combined with loops, conditions, pipes, and file operations, they form the foundation for creating powerful automation solutions.
Conclusion
Mastering the basics of Bash is like unlocking a new level of control over your system. What might seem like a simple black terminal window is actually a powerful gateway to automation, customization, and deeper interaction with your machine.
Throughout this guide, we've explored:
The core purpose of the Bash shell and how it fits into the Unix philosophy
The difference between login and interactive shells, helping you understand where your configuration lives and when it gets loaded
The essential command-line operations for navigating files and directories with confidence
And finally, how to work with file permissions numerically, giving you the tools to manage access with precision and clarity
With these foundational skills in place, you’re not just using your system—you’re starting to speak its language. You can automate repetitive tasks, customize your environment, and handle your files and scripts with authority.
But remember: this is just the beginning. Bash has many more layers—loops, conditionals, scripting logic, functions, piping and redirection, job control, and beyond. Each new concept builds on the foundation you’ve just laid.





