TOOLS & TIPS

Command Line Essentials

25 min read Intermediate

The command line (also called the terminal, console, or shell) is one of the most powerful tools available to a developer. While graphical interfaces are intuitive, the command line is faster, more flexible, and automatable. Every serious developer, system administrator, and DevOps engineer uses it daily.

If the command line feels intimidating, that is completely normal. This tutorial will walk you through everything you need to become comfortable and productive. By the end, you will navigate your file system, manage files, search for content, and chain commands together like a pro.

What is the Terminal?

The terminal is a text-based interface where you type commands and the computer executes them. Instead of clicking icons and navigating menus, you type instructions directly. The program that interprets your commands is called a shell.

Common shells include:

  • Bash (Bourne Again Shell) — The default on most Linux distributions and older macOS versions. The most widely used shell.
  • Zsh (Z Shell) — The default on macOS since Catalina. Similar to Bash with extra features like better tab completion and themes.
  • PowerShell — The default on Windows. Uses different commands than Bash/Zsh.
  • cmd.exe — The legacy Windows command prompt. Limited compared to PowerShell.

This tutorial focuses on Bash/Zsh commands (Mac and Linux), which are also available on Windows through WSL (Windows Subsystem for Linux) or Git Bash. We will note Windows equivalents where relevant.

Opening the Terminal

  • macOS: Open Spotlight (Cmd+Space), type "Terminal", press Enter. Or find it in Applications > Utilities.
  • Linux: Press Ctrl+Alt+T on most distributions, or find Terminal in your applications menu.
  • Windows: Search for "PowerShell" or "Command Prompt". For Bash commands, install WSL or Git Bash.

Navigating Directories

The first thing you need to learn is how to move around the file system. Every terminal session starts in a directory (usually your home directory), and you need to navigate to where your files are.

# pwd - Print Working Directory (where am I?)
$ pwd
/home/username
# Windows equivalent: cd (with no arguments)

# ls - List directory contents
$ ls
Desktop  Documents  Downloads  Music  Pictures

# ls with options
$ ls -l              # Long format (permissions, size, date)
$ ls -a              # Show hidden files (files starting with .)
$ ls -la             # Both: long format + hidden files
$ ls -lh             # Human-readable file sizes (KB, MB, GB)
# Windows equivalent: dir

# Sample output of ls -la:
drwxr-xr-x  5 user user 4096 Jan 15 10:30 .
drwxr-xr-x  3 user user 4096 Jan 10 08:00 ..
-rw-r--r--  1 user user  220 Jan 10 08:00 .bashrc
drwxr-xr-x  2 user user 4096 Jan 15 09:00 Documents
-rw-r--r--  1 user user 1256 Jan 15 10:30 notes.txt

# cd - Change Directory
$ cd Documents           # Move into Documents
$ cd ..                  # Go up one level (parent directory)
$ cd ../..               # Go up two levels
$ cd ~                   # Go to home directory (shortcut)
$ cd /                   # Go to root directory
$ cd -                   # Go to previous directory (toggle back)
$ cd ~/Projects/website  # Absolute path from home
# Windows equivalent: cd (same command, different path format)
Tip: Press Tab to auto-complete file and directory names. Type the first few characters and hit Tab. If there are multiple matches, press Tab twice to see all options. This saves enormous amounts of typing and prevents typos.

File Operations

Creating, copying, moving, and deleting files are the bread and butter of command line work.

# touch - Create an empty file (or update timestamp)
$ touch index.html
$ touch style.css script.js    # Create multiple files at once
# Windows equivalent: New-Item index.html (PowerShell)

# mkdir - Make Directory
$ mkdir projects                # Create one directory
$ mkdir -p projects/web/css     # Create nested directories
# The -p flag creates parent directories as needed
# Windows equivalent: mkdir (same command)

# cp - Copy files
$ cp file.txt backup.txt                   # Copy a file
$ cp file.txt ~/Documents/                 # Copy to another location
$ cp -r projects/ projects-backup/         # Copy a directory (-r = recursive)
# Windows equivalent: copy (files), xcopy or robocopy (directories)

# mv - Move or Rename files
$ mv old-name.txt new-name.txt             # Rename a file
$ mv file.txt ~/Documents/                 # Move to another directory
$ mv file.txt ~/Documents/renamed.txt      # Move AND rename
$ mv *.css css/                            # Move all CSS files to css folder
# Windows equivalent: move (move), ren (rename)

# rm - Remove (delete) files
$ rm file.txt                   # Delete a file (NO UNDO!)
$ rm -r directory/              # Delete a directory and all contents
$ rm -i file.txt                # Interactive: asks for confirmation
$ rm *.log                      # Delete all .log files
# Windows equivalent: del (files), rmdir /s (directories)
Warning: The rm command permanently deletes files. There is no trash can, no undo. Double-check your command before pressing Enter, especially with rm -r (recursive delete). Never run rm -rf / — it will attempt to delete your entire system.

Viewing File Contents

You often need to look at file contents without opening an editor. These commands let you do that quickly.

# cat - Display entire file contents
$ cat index.html              # Print file to terminal
$ cat file1.txt file2.txt     # Concatenate and display multiple files
# Windows equivalent: type

# less - View file with scrolling (press q to quit)
$ less large-log-file.txt
# Navigate: Space (page down), b (page up), /search (find text)
# q to quit
# Windows equivalent: more

# head - Show first N lines of a file
$ head index.html             # First 10 lines (default)
$ head -n 5 index.html        # First 5 lines
$ head -n 20 *.css            # First 20 lines of each CSS file

# tail - Show last N lines of a file
$ tail error.log              # Last 10 lines (default)
$ tail -n 20 error.log        # Last 20 lines
$ tail -f server.log          # Follow: watch file in real time (Ctrl+C to stop)
# tail -f is incredibly useful for watching live log files

# wc - Word count
$ wc index.html               # Lines, words, characters
$ wc -l index.html            # Line count only
$ wc -w article.txt           # Word count only

Searching for Files and Content

Finding files and searching within files are two of the most common tasks. These commands are enormously powerful.

# grep - Search for text INSIDE files
$ grep "error" server.log              # Find lines containing "error"
$ grep -i "error" server.log           # Case-insensitive search
$ grep -n "TODO" *.js                  # Show line numbers
$ grep -r "console.log" src/           # Recursive: search all files in directory
$ grep -rn "function" --include="*.js" # Search only .js files
$ grep -c "error" server.log           # Count matching lines
$ grep -v "debug" server.log           # Invert: lines NOT containing "debug"
# Windows equivalent: findstr (cmd) or Select-String (PowerShell)

# find - Search for files BY NAME or attributes
$ find . -name "*.css"                 # Find all CSS files from current dir
$ find . -name "*.js" -not -path "*/node_modules/*"  # Exclude node_modules
$ find ~/Projects -type d -name "src"  # Find directories named "src"
$ find . -type f -size +1M             # Files larger than 1MB
$ find . -type f -mtime -7             # Files modified in last 7 days
$ find . -name "*.tmp" -delete         # Find and delete (use carefully!)
# Windows equivalent: dir /s (basic), Get-ChildItem -Recurse (PowerShell)
Tip: For faster file content searching, consider installing ripgrep (rg). It is significantly faster than grep for large codebases and has more developer-friendly defaults, like automatically ignoring .gitignore patterns.

File Permissions Basics

On Unix/Linux/Mac systems, every file and directory has permission settings that control who can read, write, or execute it. Understanding permissions is essential for server management and security.

# View permissions with ls -l
$ ls -l
-rw-r--r--  1 user group  1256 Jan 15 10:30 index.html
drwxr-xr-x  2 user group  4096 Jan 15 09:00 images/

# Permission string breakdown: -rw-r--r--
# Position 1:   - (file) or d (directory)
# Positions 2-4: Owner permissions  (rw- = read, write, no execute)
# Positions 5-7: Group permissions  (r-- = read only)
# Positions 8-10: Others permissions (r-- = read only)

# r = read (4)    w = write (2)    x = execute (1)

# chmod - Change permissions
$ chmod 755 script.sh          # rwxr-xr-x (owner: all, others: read+execute)
$ chmod 644 index.html         # rw-r--r-- (owner: read+write, others: read)
$ chmod +x deploy.sh           # Add execute permission for everyone
$ chmod u+w file.txt           # Add write permission for owner (u=user)
$ chmod -R 755 public/         # Recursive: apply to all files in directory

# Common permission numbers:
# 755: Directories, executable scripts
# 644: Regular files (HTML, CSS, images)
# 600: Private files (SSH keys, .env)
# 777: Everyone can do everything (AVOID - security risk)

Piping and Redirection

Piping and redirection are what make the command line truly powerful. They let you chain commands together and direct output to files. This is where the command line goes from "useful" to "indispensable."

# Pipe ( | ) - Send output of one command as input to another
$ ls -la | less                     # Scroll through a long directory listing
$ cat server.log | grep "error"     # Search for errors in a log
$ history | grep "git"              # Find previous git commands you ran
$ ps aux | grep "node"              # Find running Node.js processes
$ cat names.txt | sort | uniq       # Sort and remove duplicates

# Chaining pipes (the real power)
$ grep -r "TODO" src/ | wc -l      # Count all TODO comments in your code
$ cat access.log | grep "404" | wc -l  # Count 404 errors in access log

# Redirect output to a file
$ echo "Hello World" > file.txt     # Write to file (overwrites!)
$ echo "Another line" >> file.txt   # Append to file (adds to end)
$ ls -la > directory-listing.txt    # Save directory listing to file
$ grep "error" log.txt > errors.txt # Save search results to file

# Redirect errors
$ command 2> errors.txt             # Send error output to file
$ command > output.txt 2>&1         # Send both output AND errors to file
$ command > /dev/null 2>&1          # Suppress all output (silent mode)
Tip: Be careful with > (single arrow) — it overwrites the file completely. Use >> (double arrow) to append. If you accidentally overwrite an important file, there is no undo.

Essential Keyboard Shortcuts

These shortcuts will dramatically speed up your terminal workflow:

Shortcut Action
TabAuto-complete file/directory names
Up/Down arrowsCycle through command history
Ctrl+CCancel/stop the current command
Ctrl+LClear the terminal screen
Ctrl+AMove cursor to beginning of line
Ctrl+EMove cursor to end of line
Ctrl+UDelete from cursor to beginning of line
Ctrl+KDelete from cursor to end of line
Ctrl+RSearch command history (reverse search)
Ctrl+DExit the terminal (or send EOF)
!!Repeat the last command (e.g., sudo !!)

Package Managers

Package managers are command-line tools that install, update, and manage software on your system. Think of them as an app store for the terminal. Different operating systems have different package managers:

# macOS: Homebrew (https://brew.sh)
$ brew install node          # Install Node.js
$ brew install git           # Install Git
$ brew update                # Update Homebrew itself
$ brew upgrade               # Upgrade all installed packages
$ brew list                  # See what's installed

# Ubuntu/Debian Linux: apt
$ sudo apt update            # Update package lists
$ sudo apt install nodejs    # Install Node.js
$ sudo apt upgrade           # Upgrade all packages
$ sudo apt remove nodejs     # Remove a package

# Fedora/RHEL Linux: dnf
$ sudo dnf install nodejs
$ sudo dnf update

# Windows: winget (built-in) or Chocolatey
$ winget install Git.Git
$ choco install nodejs

# Programming-specific package managers:
$ npm install express        # Node.js packages
$ pip install flask          # Python packages
$ composer require laravel   # PHP packages

Practical Real-World Examples

Here are some common tasks that demonstrate the power of combining commands:

# Find all JavaScript files larger than 100KB
$ find . -name "*.js" -size +100k

# Count lines of code in a project (excluding node_modules)
$ find . -name "*.js" -not -path "*/node_modules/*" | xargs wc -l

# Find and replace text across multiple files
$ grep -rl "old-text" src/ | xargs sed -i 's/old-text/new-text/g'

# Show disk usage of current directory, sorted by size
$ du -sh */ | sort -rh

# Download a file from the internet
$ curl -O https://example.com/file.zip
$ wget https://example.com/file.zip

# Check if a website is responding
$ curl -I https://example.com

# Watch a log file in real time, filtering for errors
$ tail -f /var/log/app.log | grep --line-buffered "ERROR"

# Create a compressed backup of a directory
$ tar -czf backup-$(date +%Y%m%d).tar.gz project/

# Find which process is using a specific port
$ lsof -i :3000
# or
$ ss -tlnp | grep 3000

Key Takeaways

  • The terminal is faster and more powerful than graphical tools for file management, searching, and automation.
  • Master the basics first: cd, ls, pwd, mkdir, touch, cp, mv, rm.
  • Use grep to search inside files and find to search for files by name.
  • Tab auto-completion and Ctrl+R (history search) are your best friends.
  • Piping (|) lets you chain commands together for powerful workflows.
  • Be very careful with rm — there is no undo.
  • Understand file permissions (644 for files, 755 for directories and scripts).
  • Use package managers to install software cleanly.
  • Practice daily — the command line becomes natural with repetition.