Skip to main content

📁 Lesson 2.3: Working with Files and Directories

Create, copy, move, rename, and delete — the essential file operations.

🎯 Learning Objectives

  • Create files with touch and directories with mkdir
  • Copy files and directories with cp
  • Move and rename with mv
  • Delete files with rm and directories with rmdir
  • Use wildcards to work with multiple files at once
  • Find files with find and locate

Estimated Time: 45 minutes

📑 In This Lesson

Creating Files

touch — Create an Empty File

The simplest way to create a new, empty file:

# Create a single file
touch notes.txt

# Create multiple files at once
touch file1.txt file2.txt file3.txt

# Verify they exist
ls -l notes.txt file1.txt file2.txt file3.txt

💡 What touch Really Does

Technically, touch updates a file's timestamp. If the file doesn't exist, it creates an empty one as a side effect. If the file already exists, touch updates its "last modified" time without changing its contents.

Creating Files with Content

You can create files with content using redirection:

# Create a file with one line of text
echo "Hello, Linux!" > greeting.txt

# View the contents
cat greeting.txt
# Output: Hello, Linux!

# Append more text (>> adds to the end, > overwrites)
echo "This is a second line." >> greeting.txt

cat greeting.txt
# Output:
# Hello, Linux!
# This is a second line.

🔴 > vs >> — Know the Difference!

> overwrites the file — any existing content is destroyed. >> appends to the end. This is one of the most common mistakes beginners make. When in doubt, use >>.

graph LR A["echo 'Hi' > file.txt"] -->|Overwrites| B["file.txt
contains: Hi"] C["echo 'Bye' >> file.txt"] -->|Appends| D["file.txt
contains: Hi
Bye"] style A fill:#ef4444,stroke:#b91c1c,color:#fff style C fill:#22c55e,stroke:#166534,color:#fff

Creating Directories

mkdir — Make Directory

# Create a single directory
mkdir projects

# Create multiple directories
mkdir photos videos music

# Create nested directories (parent + child in one command)
mkdir -p projects/website/css

# The -p flag creates all necessary parent directories
# Without -p, this would fail if "projects" or "website" didn't exist

✅ Always Use mkdir -p

The -p (parents) flag is your friend. It creates the full path of directories and doesn't complain if they already exist. There's almost no reason to use mkdir without it.

# Create a project structure in one shot
mkdir -p myproject/{src,tests,docs,assets/{images,fonts}}

# See what we built
tree myproject

Output:

myproject
├── assets
│   ├── fonts
│   └── images
├── docs
├── src
└── tests

6 directories, 0 files

💡 Brace Expansion

The {src,tests,docs} syntax is called brace expansion. Bash expands it into multiple arguments: myproject/src myproject/tests myproject/docs. You can use this with any command, not just mkdir.

Copying Files and Directories

cp — Copy

# Copy a file
cp notes.txt notes_backup.txt

# Copy a file to another directory
cp notes.txt ~/Documents/

# Copy a file to another directory with a new name
cp notes.txt ~/Documents/my_notes.txt

# Copy multiple files to a directory
cp file1.txt file2.txt file3.txt ~/Documents/

Copying Directories

To copy a directory and everything inside it, you need the -r (recursive) flag:

# Copy an entire directory
cp -r projects projects_backup

# -r means "recursive" — it copies the directory and all its contents
# Without -r, cp refuses to copy directories
Option Meaning
-r Recursive — copy directories and their contents
-i Interactive — ask before overwriting
-v Verbose — show what's being copied
-u Update — only copy if source is newer
# A safe, verbose recursive copy
cp -riv projects projects_backup

Moving and Renaming

mv — Move (and Rename)

In Linux, moving and renaming are the same operation:

# Rename a file (move it to a new name in the same directory)
mv notes.txt my_notes.txt

# Move a file to another directory
mv my_notes.txt ~/Documents/

# Move and rename at the same time
mv my_notes.txt ~/Documents/important_notes.txt

# Move a directory (no -r needed, unlike cp)
mv projects ~/Documents/projects

# Move multiple files to a directory
mv file1.txt file2.txt file3.txt ~/Documents/

⚠️ mv Overwrites Silently

If the destination file already exists, mv will overwrite it without asking. Use mv -i (interactive) to get a confirmation prompt, or mv -n (no-clobber) to prevent overwriting entirely.

graph LR A["mv old.txt new.txt"] -->|"Same directory"| B["Renames the file"] C["mv file.txt /tmp/"] -->|"Different directory"| D["Moves the file"] E["mv file.txt /tmp/other.txt"] -->|"Different directory + name"| F["Moves AND renames"] style B fill:#6366f1,stroke:#4338ca,color:#fff style D fill:#22c55e,stroke:#166534,color:#fff style F fill:#f59e0b,stroke:#b45309,color:#fff

Deleting Files and Directories

🔴 There Is No Trash Can

In the Linux terminal, delete means delete. There is no Recycle Bin (Windows), no Trash (macOS), no undo, no "are you sure?" (unless you add the -i flag). Once a file is removed with rm, it's gone. Always double-check before pressing Enter.

rm — Remove Files

# Delete a single file
rm notes.txt

# Delete with confirmation prompt
rm -i notes.txt
# Output: rm: remove regular file 'notes.txt'? y

# Delete multiple files
rm file1.txt file2.txt file3.txt

# Delete all .txt files in the current directory
rm *.txt

rm -r — Remove Directories

# Remove a directory and everything inside it
rm -r old_project

# Remove with confirmation for each file
rm -ri old_project

# Force remove (no prompts, even for read-only files)
rm -rf old_project

🔴 The rm -rf Warning

rm -rf is the most dangerous command in Linux. It recursively force-deletes everything you point it at with no confirmation. Never run rm -rf / or rm -rf ~. Always double-check the path before using -rf. A typo can wipe your entire system.

rmdir — Remove Empty Directories

# Only works if the directory is empty
rmdir empty_folder

# Fails if the directory contains anything
rmdir projects
# Output: rmdir: failed to remove 'projects': Directory not empty

✅ Safe Deletion Habits

  • Use rm -i until you're confident (the -i flag asks before each delete)
  • Run ls first to see what you're about to delete
  • Use rm -ri for directories so you confirm each file
  • Consider adding alias rm='rm -i' to your .bashrc for permanent safety

Wildcards

Wildcards (also called globs) let you match multiple files with a pattern:

Wildcard Matches Example Matches These
* Zero or more characters *.txt notes.txt, readme.txt, .txt
? Exactly one character file?.txt file1.txt, fileA.txt, not file12.txt
[abc] One character from the set file[123].txt file1.txt, file2.txt, file3.txt
[0-9] One character from the range log[0-9].txt log0.txt through log9.txt
# List all HTML files
ls *.html

# Copy all images to a backup
cp *.jpg *.png ~/backup/

# Move all files starting with "report"
mv report* ~/Documents/

# Delete all .tmp files
rm *.tmp

# List files with exactly 3-character extensions
ls *.???

💡 Test Before You Delete

Before running rm *.something, first run ls *.something to see which files match. This simple habit prevents accidental deletions.

Finding Files

When you need to find a file but don't know exactly where it is:

find — Search by Criteria

# Find files by name (starting from current directory)
find . -name "notes.txt"

# Find all .txt files under your home directory
find ~ -name "*.txt"

# Find files by name (case-insensitive)
find ~ -iname "readme*"

# Find only directories with a name
find /etc -type d -name "apt"

# Find only files (not directories)
find ~ -type f -name "*.log"

# Find files larger than 100MB
find / -type f -size +100M 2>/dev/null

# Find files modified in the last 7 days
find ~ -type f -mtime -7

💡 The 2>/dev/null Trick

When searching system directories, you'll see "Permission denied" errors for directories you can't read. Adding 2>/dev/null hides those errors by redirecting them to a virtual trash can. We'll cover redirection in more detail in Module 8.

locate — Fast Search by Name

The locate command uses a pre-built database and is much faster than find:

# Install locate
sudo apt install mlocate -y

# Update the database (run this first, and after adding new files)
sudo updatedb

# Search for a file
locate notes.txt

# Case-insensitive search
locate -i readme

🐧 find vs locate

find searches the live filesystem in real-time — always accurate but slower. locate searches a cached database — lightning fast but might miss recently created files. Use sudo updatedb to refresh locate's database.

🍎 On macOS

The find command works the same way on macOS. Instead of locate, macOS has mdfind, which uses the Spotlight index: mdfind notes.txt. It's fast and always up to date. You can also install locate via Homebrew if you prefer the Linux version.

which and type — Find Commands

# Where is a command located?
which ls
# Output: /usr/bin/ls

which python3
# Output: /usr/bin/python3

# More detailed info about a command
type ls
# Output: ls is aliased to 'ls --color=auto'

type cd
# Output: cd is a shell builtin

Exercises

🏋️ Exercise 1: Build a Project

Create the following structure using mkdir -p and touch:

my_website/
├── index.html
├── about.html
├── css/
│   └── style.css
├── js/
│   └── app.js
└── images/
💡 Solution
mkdir -p my_website/{css,js,images}
touch my_website/index.html
touch my_website/about.html
touch my_website/css/style.css
touch my_website/js/app.js

# Verify
tree my_website

🏋️ Exercise 2: Copy and Move

  1. Create a file: echo "Important data" > data.txt
  2. Copy it: cp data.txt data_backup.txt
  3. Create a directory: mkdir archive
  4. Move the backup: mv data_backup.txt archive/
  5. Rename the original: mv data.txt info.txt
  6. Verify everything: ls -la and ls archive/
💡 Expected Result

You should have info.txt in the current directory and data_backup.txt inside the archive/ folder.

🏋️ Exercise 3: Wildcards Practice

Set up some test files, then use wildcards:

# Create test files
touch report_jan.txt report_feb.txt report_mar.txt
touch photo1.jpg photo2.jpg photo3.png
touch notes.md readme.md

# Now try:
ls *.txt            # All text files
ls report*          # All reports
ls photo?.jpg       # Photos 1-9 (single digit)
ls *.md             # All markdown files

# Move all reports to a folder
mkdir reports
mv report_*.txt reports/

# Verify
ls reports/

🏋️ Exercise 4: Find Things

# Find all .txt files in your home directory
find ~ -name "*.txt" -type f 2>/dev/null

# Find where the "bash" command lives
which bash

# Find all directories named "Documents" under /home
find /home -type d -name "Documents" 2>/dev/null

🏋️ Exercise 5: Clean Up

Remove the test files and directories you created:

# First, see what's there
ls

# Remove files
rm photo*.jpg photo*.png notes.md readme.md info.txt

# Remove directories
rm -r my_website reports archive

# Verify it's clean
ls
💡 Tip

Always run ls before rm to confirm what you're deleting. Especially when using wildcards — one wrong character can delete the wrong files.

Knowledge Check

❓ Question 1

What's the difference between > and >>?

❓ Question 2

Which command copies a directory and all its contents?

❓ Question 3

What does the wildcard *.txt match?

❓ Question 4

You accidentally typed rm important_file.txt and pressed Enter. Can you undo it?

Quick Reference

Command What It Does Example
touch Create an empty file touch file.txt
mkdir -p Create directories (including parents) mkdir -p a/b/c
cp Copy a file cp src.txt dest.txt
cp -r Copy a directory recursively cp -r mydir backup
mv Move or rename mv old.txt new.txt
rm Delete a file rm file.txt
rm -r Delete a directory and contents rm -r old_dir
find Search for files by criteria find ~ -name "*.txt"
which Find where a command lives which python3

Summary

🎉 Key Takeaways

  • touch creates empty files; echo "text" > file creates files with content
  • mkdir -p creates directories (and any missing parents)
  • cp copies files; cp -r copies directories
  • mv moves and renames; it works on both files and directories
  • rm deletes permanently — there is no undo! Use -i for safety
  • > overwrites, >> appends — know the difference
  • Wildcards (*, ?, []) let you work with multiple files at once
  • find searches in real-time; locate uses a cached database

🎉 Module 2 Complete!

You can now open the terminal, navigate the filesystem, and manage files and directories. These are the foundational skills for everything else in Linux.

🚀 What's Next?

In Module 3, you'll learn how Linux controls who can access what — users, groups, and the powerful permission system that keeps everything secure.