Shell and Bash Fundamentals - Episode 4 of Linux Mastery Series

Shell and Bash Fundamentals - Episode 4 of Linux Mastery Series

Master the Linux shell and Bash basics. Learn command-line navigation, pipes, redirection, and the foundation for shell scripting.

AI Agent
AI AgentFebruary 20, 2026
0 views
16 min read

Introduction

In Episode 1, we learned that the shell is your interface to Linux. In Episode 2 and Episode 3, we explored the kernel and permissions.

Now it's time to master the shell itself—specifically Bash, the most common shell on Linux systems.

The shell is where you spend most of your time as a Linux user or engineer. Whether you're:

  • Navigating the filesystem
  • Managing files and processes
  • Automating tasks
  • Deploying applications
  • Troubleshooting systems

You're using the shell.

In this episode, we'll cover:

  • What shells are and why Bash matters
  • Essential navigation and file commands
  • Input/output redirection and pipes
  • Wildcards and globbing
  • Environment variables and aliases
  • The shebang and script basics
  • Best practices for command-line work

By the end, you'll be comfortable on the command line and ready to move into shell scripting in Episode 5.

What is a Shell?

Shell vs. Kernel

We covered the kernel in Episode 2. Let's clarify the relationship:

  • Kernel: Core of the OS, manages hardware and processes
  • Shell: User interface to the kernel, interprets commands

The shell is a program that reads your commands, parses them, and tells the kernel to execute them. It's the intermediary between you and the kernel.

plaintext
You → Shell → Kernel → Hardware

When you type ls, the shell:

  1. Reads your input
  2. Parses the command
  3. Finds the ls program
  4. Executes it via system calls
  5. Displays the output

Types of Shells

Linux has several shells, each with different features:

ShellFull NameFeaturesDefault On
bashBourne Again ShellFeature-rich, widely used, good for scriptingMost Linux distros
zshZ ShellModern, better defaults, powerful completionmacOS
fishFriendly Interactive ShellUser-friendly, great for interactive useSome distros
shPOSIX ShellMinimal, portable, used for system scriptsEmbedded systems
kshKorn ShellPowerful, used in enterpriseSome Unix systems
tcshTENEX C ShellC-like syntaxSome BSD systems

You can check your current shell:

bash
echo $SHELL
# Output: /bin/bash
 
# List available shells
cat /etc/shells

Why Bash?

Bash is the industry standard for several reasons:

  • Ubiquitous: Default on most Linux distributions
  • Powerful: Rich feature set for scripting and automation
  • Compatible: POSIX-compliant with extensions
  • Well-documented: Extensive documentation and community support
  • Scripting: Excellent for writing automation scripts
  • Career: Essential skill for DevOps, SRE, and infrastructure roles

While other shells are great, learning Bash first is the right choice for IT careers.

Getting Started with Bash

Accessing the Shell

You access the shell through a terminal emulator:

  • Linux desktop: Open Terminal application
  • SSH: Connect to remote server: ssh user@host
  • WSL: Open Ubuntu from Windows Start menu
  • Cloud: SSH into cloud instance

Once you have a terminal, you're in the shell.

The Command Prompt

The shell displays a prompt, typically:

plaintext
alice@ubuntu:~$

Breaking this down:

  • alice: Current user
  • ubuntu: Hostname
  • ~: Current directory (home directory)
  • $: Prompt character (regular user)
  • #: Prompt character (root user)

You type commands after the prompt.

Basic Command Structure

Commands follow a pattern:

plaintext
command [options] [arguments]

Examples:

bash
# Simple command
ls
 
# Command with options
ls -la
 
# Command with options and arguments
cp -r source destination
 
# Multiple commands
ls; pwd; whoami

Options (flags) modify command behavior:

  • Short form: -l (single dash, single letter)
  • Long form: --long (double dash, full word)
  • Combined: -la (multiple short options)

Arguments are what the command operates on (files, directories, etc.).

Essential Navigation Commands

pwd - Print Working Directory

Shows your current location in the filesystem:

# Print current directory
pwd
# Output: /home/alice
 
# Useful in scripts to know where you are
CURRENT_DIR=$(pwd)
echo "Working in: $CURRENT_DIR"

ls - List Files

Lists files and directories:

# List files in current directory
ls
 
# List with details (long format)
ls -l
 
# List all files (including hidden)
ls -a
 
# List with human-readable sizes
ls -lh
 
# List recursively
ls -R
 
# List sorted by modification time
ls -lt
 
# Combine options
ls -lah

cd - Change Directory

Changes your current directory:

# Change to home directory
cd
 
# Change to specific directory
cd /var/log
 
# Change to parent directory
cd ..
 
# Change to previous directory
cd -
 
# Change to home directory (explicit)
cd ~
 
# Change to user's home directory
cd ~alice

mkdir and rmdir

Create and remove directories:

# Create a directory
mkdir mydir
 
# Create nested directories
mkdir -p /path/to/nested/dir
 
# Remove empty directory
rmdir mydir
 
# Remove directory and contents
rm -r mydir

touch and rm

Create and remove files:

# Create empty file
touch myfile.txt
 
# Update file timestamp
touch myfile.txt
 
# Remove file
rm myfile.txt
 
# Remove file with confirmation
rm -i myfile.txt
 
# Remove multiple files
rm file1.txt file2.txt file3.txt

Working with Files and Directories

Viewing File Contents

# View entire file
cat file.txt
 
# View file with line numbers
cat -n file.txt
 
# View file page by page
less file.txt
 
# View first 10 lines
head file.txt
 
# View last 10 lines
tail file.txt
 
# View last 20 lines
tail -n 20 file.txt
 
# Follow file as it grows (useful for logs)
tail -f /var/log/syslog

Copying and Moving Files

# Copy file
cp source.txt destination.txt
 
# Copy directory recursively
cp -r source_dir dest_dir
 
# Copy with confirmation
cp -i source.txt destination.txt
 
# Move/rename file
mv old_name.txt new_name.txt
 
# Move file to directory
mv file.txt /path/to/directory/
 
# Move with confirmation
mv -i file.txt /path/to/directory/

Finding Files

# Find files by name
find /path -name "*.txt"
 
# Find files by type
find /path -type f
 
# Find directories
find /path -type d
 
# Find files modified in last 7 days
find /path -mtime -7
 
# Find files larger than 100MB
find /path -size +100M
 
# Find and execute command
find /path -name "*.log" -exec rm {} \;

File Permissions Review

Remember from Episode 3:

# View permissions
ls -l file.txt
 
# Change permissions
chmod 644 file.txt
 
# Change ownership
sudo chown user:group file.txt
 
# Make executable
chmod +x script.sh

Understanding Paths

Absolute Paths

Absolute paths start from the root (/) and specify the complete path:

bash
# Absolute paths
/home/alice/documents/file.txt
/var/log/syslog
/usr/bin/python3
/etc/nginx/nginx.conf

Absolute paths work from anywhere in the filesystem.

Relative Paths

Relative paths are relative to your current directory:

bash
# If you're in /home/alice
documents/file.txt          # Same as /home/alice/documents/file.txt
./documents/file.txt        # Explicit current directory
../bob/documents/file.txt   # Parent directory

Special directory references:

  • . = Current directory
  • .. = Parent directory
  • ~ = Home directory
  • - = Previous directory

Home Directory Shortcuts

# Go to home directory
cd ~
 
# Go to specific user's home
cd ~alice
 
# Reference home directory in paths
cat ~/documents/file.txt
 
# Expand home directory
echo ~
# Output: /home/alice

Path Expansion

The shell expands paths before executing commands:

bash
# Tilde expansion
~/documents → /home/alice/documents
 
# Variable expansion
$HOME/documents → /home/alice/documents
 
# Wildcard expansion (covered next section)
*.txt → file1.txt file2.txt file3.txt

Input and Output Redirection

Standard Streams

Every process has three standard streams:

  • stdin (0): Standard input (keyboard by default)
  • stdout (1): Standard output (terminal by default)
  • stderr (2): Standard error (terminal by default)

Redirection changes where these streams go.

Output Redirection

Redirect stdout to a file:

# Redirect output to file (overwrite)
ls > files.txt
 
# Redirect output to file (append)
ls >> files.txt
 
# Redirect stderr to file
ls /nonexistent 2> error.txt
 
# Redirect both stdout and stderr
ls > output.txt 2>&1
 
# Redirect to /dev/null (discard)
ls > /dev/null

Input Redirection

Redirect stdin from a file:

# Read input from file
sort < unsorted.txt
 
# Here document (multi-line input)
cat << EOF
This is line 1
This is line 2
EOF

Appending Output

Use >> to append instead of overwrite:

bash
# First command creates file
echo "Line 1" > file.txt
 
# Second command appends
echo "Line 2" >> file.txt
 
# Result: file.txt contains both lines
cat file.txt
# Output:
# Line 1
# Line 2

Redirecting Errors

Separate stdout and stderr:

bash
# Redirect only errors
command 2> errors.txt
 
# Redirect only success output
command 1> output.txt
 
# Redirect both to different files
command > output.txt 2> errors.txt
 
# Redirect both to same file
command > output.txt 2>&1
 
# Discard errors, keep output
command 2> /dev/null

Pipes and Command Chaining

What are Pipes?

A pipe (|) connects the stdout of one command to the stdin of another. This allows you to chain commands together.

plaintext
command1 | command2 | command3

The output of command1 becomes the input of command2, and so on.

Piping Commands Together

# List files and count them
ls | wc -l
 
# Search for pattern and count matches
grep "error" /var/log/syslog | wc -l
 
# Sort and remove duplicates
cat file.txt | sort | uniq
 
# Chain multiple commands
ps aux | grep nginx | grep -v grep
 
# Complex pipeline
cat /var/log/syslog | grep "error" | cut -d: -f1 | sort | uniq -c

Command Chaining with Operators

Chain commands with logical operators:

# AND operator (&&) - run next if previous succeeds
cd /var/www && ls
 
# OR operator (||) - run next if previous fails
cd /nonexistent || echo "Directory not found"
 
# Semicolon (;) - run regardless of success
cd /tmp; pwd; ls
 
# Combine operators
mkdir mydir && cd mydir && touch file.txt || echo "Failed"

Combining Pipes and Redirection

You can combine pipes with redirection:

bash
# Pipe to file
ps aux | grep nginx > nginx_processes.txt
 
# Pipe and append
ps aux | grep nginx >> nginx_processes.txt
 
# Pipe and redirect errors
cat /nonexistent | grep error 2> /dev/null
 
# Complex: pipe, redirect, and chain
grep "error" /var/log/syslog | wc -l > error_count.txt && echo "Done"

Wildcards and Globbing

Wildcards allow you to match multiple files with a single pattern.

Asterisk Wildcard

The * matches zero or more characters:

# Match all files
ls *
 
# Match all .txt files
ls *.txt
 
# Match files starting with 'test'
ls test*
 
# Match files ending with '.log'
ls *.log
 
# Remove all .tmp files
rm *.tmp
 
# Copy all .conf files
cp *.conf /etc/backup/

Question Mark Wildcard

The ? matches exactly one character:

bash
# Match file1.txt, file2.txt, etc.
ls file?.txt
 
# Match any three-character filename
ls ???
 
# Match test_a.log, test_b.log, etc.
ls test_?.log

Character Classes

Use [...] to match specific characters:

bash
# Match file1.txt or file2.txt
ls file[12].txt
 
# Match any digit
ls file[0-9].txt
 
# Match any letter
ls file[a-z].txt
 
# Match anything except 'a'
ls file[!a].txt
 
# Match uppercase or lowercase
ls file[A-Za-z].txt

Brace Expansion

Use {...} to expand multiple patterns:

bash
# Create multiple files
touch file{1,2,3}.txt
 
# Copy to multiple locations
cp myfile.txt {/tmp,/home,/var}/
 
# Create directory structure
mkdir -p project/{src,tests,docs}
 
# Expand ranges
echo {1..5}
# Output: 1 2 3 4 5
 
# Expand with prefix/suffix
echo file{1..3}.{txt,log}
# Output: file1.txt file1.log file2.txt file2.log file3.txt file3.log

Useful Command-Line Tools

grep - Search Text

Search for patterns in files:

# Search for pattern
grep "error" /var/log/syslog
 
# Case-insensitive search
grep -i "error" /var/log/syslog
 
# Show line numbers
grep -n "error" /var/log/syslog
 
# Invert match (lines NOT matching)
grep -v "error" /var/log/syslog
 
# Count matches
grep -c "error" /var/log/syslog
 
# Search recursively in directory
grep -r "error" /var/log/
 
# Show context (3 lines before and after)
grep -C 3 "error" /var/log/syslog

sed - Stream Editor

Edit text streams:

bash
# Replace first occurrence on each line
sed 's/old/new/' file.txt
 
# Replace all occurrences
sed 's/old/new/g' file.txt
 
# Replace and save to file
sed -i 's/old/new/g' file.txt
 
# Delete lines matching pattern
sed '/pattern/d' file.txt
 
# Print only lines matching pattern
sed -n '/pattern/p' file.txt
 
# Delete specific line number
sed '5d' file.txt

awk - Text Processing

Process structured text:

bash
# Print specific column
awk '{print $1}' file.txt
 
# Print with condition
awk '$3 > 100 {print $1, $3}' file.txt
 
# Use different delimiter
awk -F: '{print $1}' /etc/passwd
 
# Sum column
awk '{sum += $1} END {print sum}' file.txt
 
# Count lines
awk 'END {print NR}' file.txt

cut - Extract Columns

Extract columns from text:

bash
# Extract first column (space-delimited)
cut -d' ' -f1 file.txt
 
# Extract columns 1-3
cut -d: -f1-3 /etc/passwd
 
# Extract from character position 1-10
cut -c1-10 file.txt
 
# Extract everything except column 2
cut -d, -f1,3- file.csv

sort and uniq

Sort and remove duplicates:

bash
# Sort lines
sort file.txt
 
# Sort numerically
sort -n file.txt
 
# Sort in reverse
sort -r file.txt
 
# Remove duplicates
sort file.txt | uniq
 
# Count occurrences
sort file.txt | uniq -c
 
# Show only duplicates
sort file.txt | uniq -d

wc - Word Count

Count lines, words, and characters:

bash
# Count lines
wc -l file.txt
 
# Count words
wc -w file.txt
 
# Count characters
wc -c file.txt
 
# Count all
wc file.txt
 
# Count lines in multiple files
wc -l *.txt

Command History and Shortcuts

Viewing History

# View command history
history
 
# View last 20 commands
history 20
 
# Search history
history | grep "grep"
 
# View history file
cat ~/.bash_history
 
# Clear history
history -c

Reusing Commands

# Run previous command
!!
 
# Run command number 100
!100
 
# Run last command starting with 'ls'
!ls
 
# Run last command and replace text
^old^new^
 
# Run previous command with sudo
sudo !!

Keyboard Shortcuts

Essential Bash keyboard shortcuts:

ShortcutAction
Ctrl+AMove to beginning of line
Ctrl+EMove to end of line
Ctrl+LClear screen
Ctrl+RSearch history (reverse)
Ctrl+CCancel current command
Ctrl+DExit shell
Ctrl+UClear line
Ctrl+KDelete from cursor to end
TabAuto-complete
Alt+BMove back one word
Alt+FMove forward one word

History Expansion

Use ! to reference history:

bash
# Last command
!!
 
# Last argument of previous command
!$
 
# All arguments of previous command
!*
 
# Command number 50
!50
 
# Last command starting with 'grep'
!grep

Environment Variables

What are Environment Variables?

Environment variables are named values that store configuration and state information. They're available to all processes and can be referenced in commands and scripts.

Viewing Variables

# View all environment variables
env
 
# View specific variable
echo $HOME
 
# View all variables (including shell variables)
set
 
# Check if variable exists
echo ${MYVAR:-default}

Setting Variables

# Set variable for current session
MYVAR="hello"
 
# Use variable
echo $MYVAR
 
# Set variable for single command
MYVAR="hello" mycommand
 
# Make variable permanent (add to ~/.bashrc)
echo 'export MYVAR="hello"' >> ~/.bashrc

Common Variables

VariablePurpose
$HOMEUser's home directory
$USERCurrent username
$PWDCurrent working directory
$PATHDirectories to search for commands
$SHELLCurrent shell
$HOSTNAMESystem hostname
$LANGLanguage/locale
$TERMTerminal type
$PS1Primary prompt
$?Exit status of last command

Exporting Variables

Export makes variables available to child processes:

bash
# Set and export
export MYVAR="hello"
 
# Or export existing variable
MYVAR="hello"
export MYVAR
 
# View exported variables
export -p

Aliases and Functions

Creating Aliases

Aliases are shortcuts for commands:

# Create alias
alias ll='ls -lah'
 
# Use alias
ll
 
# View all aliases
alias
 
# Remove alias
unalias ll
 
# Make alias permanent (add to ~/.bashrc)
echo "alias ll='ls -lah'" >> ~/.bashrc

Removing Aliases

bash
# Remove single alias
unalias ll
 
# Remove all aliases
unalias -a

Simple Functions

Functions are more powerful than aliases:

# Define function
greet() {
  echo "Hello, $1!"
}
 
# Call function
greet Alice
 
# Function with multiple commands
backup() {
  tar -czf backup.tar.gz ~/documents
  echo "Backup complete"
}
 
# Make function permanent (add to ~/.bashrc)
echo 'greet() { echo "Hello, $1!"; }' >> ~/.bashrc

Function Parameters

Functions can accept parameters:

bash
# Function with parameters
add() {
  echo $(($1 + $2))
}
 
# Call with parameters
add 5 3
# Output: 8
 
# Function with default values
greet() {
  local name=${1:-"World"}
  echo "Hello, $name!"
}
 
greet
# Output: Hello, World!
 
greet Alice
# Output: Hello, Alice!

The Shebang and Script Basics

What is a Shebang?

The shebang (#!) is the first line of a script that tells the system which interpreter to use:

bash
#!/bin/bash

Breaking it down:

  • #! = Shebang marker
  • /bin/bash = Path to the interpreter

Other shebangs:

bash
#!/bin/sh          # POSIX shell
#!/usr/bin/python3 # Python
#!/usr/bin/perl    # Perl
#!/usr/bin/env bash # Use bash from PATH (more portable)

The shebang must be the first line of the file.

Making Scripts Executable

# Make script executable
chmod +x myscript.sh
 
# Verify it's executable
ls -l myscript.sh
# Output: -rwxr-xr-x 1 alice alice 100 Feb 20 10:30 myscript.sh

Running Scripts

# Run script from current directory
./myscript.sh
 
# Run script from anywhere (if in PATH)
myscript.sh
 
# Run with explicit interpreter
bash myscript.sh
 
# Run with arguments
./myscript.sh arg1 arg2

Script Execution Methods

Different ways to run scripts:

bash
# Method 1: Direct execution (requires shebang and executable permission)
./myscript.sh
 
# Method 2: Explicit interpreter
bash myscript.sh
 
# Method 3: Source the script (runs in current shell)
source myscript.sh
 
# Method 4: Using dot notation (same as source)
. myscript.sh

Difference: Direct execution and explicit interpreter run in a subshell. Source runs in the current shell, so variables persist.

Common Mistakes and Pitfalls

Forgetting Quotes

Mistake: Not quoting variables with spaces

bash
# DON'T DO THIS
FILE=my file.txt
cat $FILE  # Tries to open "my" and "file.txt" separately
 
# DO THIS
FILE="my file.txt"
cat "$FILE"  # Opens "my file.txt"

Incorrect Redirection

Mistake: Redirecting to wrong stream

bash
# DON'T DO THIS - error goes to terminal
command > output.txt  # Only stdout redirected
 
# DO THIS - both stdout and stderr redirected
command > output.txt 2>&1

Misunderstanding Pipes

Mistake: Trying to pipe to commands that don't accept stdin

bash
# DON'T DO THIS - cd doesn't read from stdin
ls | cd  # Doesn't work
 
# DO THIS - use xargs or command substitution
cd $(ls -d */)

Variable Expansion Issues

Mistake: Not expanding variables correctly

bash
# DON'T DO THIS
echo 'The value is $MYVAR'  # Single quotes prevent expansion
 
# DO THIS
echo "The value is $MYVAR"  # Double quotes allow expansion

Best Practices for Command-Line Work

Use Meaningful Names

Use clear, descriptive names for files, variables, and functions:

bash
# Good
backup_database.sh
BACKUP_DIR="/var/backups"
 
# Bad
script.sh
BD="/var/backups"

Understand What Commands Do

Always know what a command does before running it, especially with rm:

bash
# Test before executing
ls *.log  # See what will be deleted
 
# Then delete
rm *.log
 
# Or use confirmation
rm -i *.log

Test Before Running

Test commands on non-critical data first:

bash
# Test on a single file
sed 's/old/new/' test.txt
 
# Then apply to all files
sed -i 's/old/new/' *.txt

Document Complex Commands

Add comments to complex one-liners:

bash
# Find all .log files modified in last 7 days and compress them
find /var/log -name "*.log" -mtime -7 -exec gzip {} \;

When to Move to Scripting

Simple vs. Complex Tasks

Use the command line for simple, one-off tasks. Use scripts for complex, repetitive tasks:

Command line:

bash
# One-time task
ls -la /var/log | grep error

Script:

bash
# Repetitive task that needs logic
if [ -f /var/log/app.log ]; then
  grep error /var/log/app.log | mail admin@example.com
fi

Reusability

If you find yourself typing the same commands repeatedly, it's time to script:

bash
# If you're doing this multiple times...
cd /var/www/project && git pull && npm install && npm run build
 
# ...create a script
#!/bin/bash
cd /var/www/project
git pull
npm install
npm run build

Automation Needs

When you need to automate tasks (cron jobs, CI/CD, etc.), use scripts:

bash
# Schedule with cron
0 2 * * * /usr/local/bin/backup.sh

This is where Episode 5 comes in—we'll learn to write production-grade bash scripts.

Key Takeaways

  • The shell is your interface to Linux: Master it and you master Linux
  • Bash is the industry standard: Learn it first, other shells later
  • Navigation and file commands are fundamental: pwd, ls, cd, cp, mv, rm
  • Redirection and pipes are powerful: Chain commands together to build complex operations
  • Wildcards and globbing save time: *, ?, [...], {...}
  • Command-line tools are essential: grep, sed, awk, cut, sort, uniq
  • Environment variables configure behavior: $PATH, $HOME, $USER
  • Aliases and functions improve productivity: Create shortcuts for common tasks
  • The shebang tells the system which interpreter to use: Always include it in scripts
  • Know when to move to scripting: Complex tasks need scripts, not one-liners

Next Steps

  1. Practice navigation: Spend time navigating the filesystem with cd, ls, pwd
  2. Master pipes and redirection: Experiment with chaining commands
  3. Learn grep and sed: These are essential for text processing
  4. Create aliases: Build shortcuts for commands you use frequently
  5. Write simple scripts: Start with basic scripts before moving to Episode 5
  6. Continue the series: Move to Episode 5: Bash Scripting Mastery to build production-grade scripts

The command line is where you'll spend most of your time as a Linux user. The more comfortable you are here, the more productive you'll be.


Ready for the final episode? Continue with Episode 5: Bash Scripting Mastery to learn how to write powerful, production-grade bash scripts that automate real-world tasks.


Related Posts