File Operations Mastery
In Lesson 1, you learned to navigate the Linux filesystem -- moving between directories, understanding paths, and building a mental map of where things live. Now it's time to shape that filesystem.
Every AI agent you deploy needs a workspace: directories for source code, configuration files, log output, and data storage. Before any agent can run, someone has to create that structure, populate it with files, and maintain it over time. That someone is you, and your tools are the file operation commands you'll learn in this lesson.
Think of file operations as the construction tools of the CLI architect. Navigation was reading the blueprint. Now you're picking up the hammer, saw, and measuring tape. By the end of this lesson, you'll be able to build, organize, and manage the directory structures that your Digital FTEs depend on.
Creating Files and Directories
Every workspace starts empty. Let's build one from scratch.
Creating Empty Files with touch
The touch command creates an empty file. If the file already exists, it updates its timestamp without changing content.
cd ~
touch my-first-file.txt
ls -l my-first-file.txt
Output:
-rw-r--r-- 1 yourname yourname 0 Feb 9 14:30 my-first-file.txt
Notice the file size is 0 -- touch creates the file but puts nothing in it. This is useful for creating placeholder files, empty logs, or files you'll populate later.
You can create multiple files at once:
touch agent.log config.yaml README.md
ls -l agent.log config.yaml README.md
Output:
-rw-r--r-- 1 yourname yourname 0 Feb 9 14:31 agent.log
-rw-r--r-- 1 yourname yourname 0 Feb 9 14:31 config.yaml
-rw-r--r-- 1 yourname yourname 0 Feb 9 14:31 README.md
Creating Directories with mkdir
Use mkdir to create directories:
mkdir my-agent
ls -d my-agent
Output:
my-agent
But what if you need a nested structure? This fails:
mkdir my-agent/src/handlers
Output:
mkdir: cannot create directory 'my-agent/src/handlers': No such file or directory
The parent directory my-agent/src doesn't exist yet. The -p flag solves this by creating all parent directories as needed:
mkdir -p my-agent/src/handlers
ls -R my-agent
Output:
my-agent:
src
my-agent/src:
handlers
my-agent/src/handlers:
The -p flag is your go-to for building workspace structures. It never fails because missing parents exist, and it doesn't complain if directories already exist.
Building a Complete Agent Workspace
Let's build a realistic workspace structure using brace expansion -- a shell feature that generates multiple directory names from a pattern:
mkdir -p ~/agents/customer-bot/{src,config,logs,data}
ls -R ~/agents/customer-bot
Output:
/home/yourname/agents/customer-bot:
config data logs src
/home/yourname/agents/customer-bot/config:
/home/yourname/agents/customer-bot/data:
/home/yourname/agents/customer-bot/logs:
/home/yourname/agents/customer-bot/src:
One command created a complete agent workspace with four organized subdirectories. This is the kind of structure your deployed agents will use: source code in src, settings in config, runtime output in logs, and persistent storage in data.
Copying Files and Directories
Once files exist, you often need duplicates -- backups, templates, or copies for different environments.
Copying a Single File
cd ~/agents/customer-bot
touch config/settings.yaml
cp config/settings.yaml config/settings.yaml.backup
ls config/
Output:
settings.yaml settings.yaml.backup
The cp command takes two arguments: source and destination. If the destination is a filename, it creates a copy with that name. If the destination is a directory, it copies the file into that directory keeping the original name:
cp config/settings.yaml data/
ls data/
Output:
settings.yaml
Copying Directories Recursively
To copy an entire directory and its contents, use the -r (recursive) flag:
cp -r config config-staging
ls -R config-staging/
Output:
config-staging/:
settings.yaml settings.yaml.backup
Without -r, attempting to copy a directory fails:
cp config config-test
Output:
cp: -r not specified; omitting directory 'config'
This is a safety mechanism -- copying directories involves potentially thousands of files, so the system requires you to explicitly confirm with -r.
Moving and Renaming Files
The mv command serves two purposes: moving files to a different location and renaming them. Under the hood, both operations are the same -- changing where a file's name points in the filesystem.
Moving a File to Another Directory
touch src/main.py
mv src/main.py src/handlers/
ls src/handlers/
Output:
main.py
The file is no longer in src/ -- it has been moved to src/handlers/.
Renaming a File
mv src/handlers/main.py src/handlers/agent_main.py
ls src/handlers/
Output:
agent_main.py
Same command, different effect. When the source and destination are in the same directory, mv renames. When they're in different directories, mv moves.
Moving and Renaming at the Same Time
mv src/handlers/agent_main.py src/app.py
ls src/
Output:
app.py handlers
The file was moved from src/handlers/ to src/ and renamed to app.py in a single operation.
Renaming Directories
mv works on directories too, without needing any special flags:
mv config-staging config-production
ls -d config-production
Output:
config-production
Deleting Files Safely
Deletion on Linux is permanent. There is no recycle bin, no trash folder, no undo. When a file is deleted, it's gone. This makes safe deletion practices essential.
Safe Deletion with rm -i
Always start with rm -i (interactive mode), which asks for confirmation before each deletion:
touch temp-file.txt
rm -i temp-file.txt
Output:
rm: remove regular empty file 'temp-file.txt'? y
You must type y and press Enter to confirm. This gives you a chance to catch mistakes before they become permanent.
Deleting Multiple Files
touch old-1.log old-2.log old-3.log
rm -i old-*.log
Output:
rm: remove regular empty file 'old-1.log'? y
rm: remove regular empty file 'old-2.log'? y
rm: remove regular empty file 'old-3.log'? y
Each file requires confirmation. For three files, this is manageable. For three hundred, you'll need the recursive approach below -- but only after verifying with ls first.
Deleting Directories with rm -r
To delete a directory and everything inside it:
rm -ri config-production
Output:
rm: descend into directory 'config-production'? y
rm: remove regular empty file 'config-production/settings.yaml'? y
rm: remove regular empty file 'config-production/settings.yaml.backup'? y
rm: remove directory 'config-production'? y
The -r flag means recursive (delete contents first, then the directory). Combined with -i, you confirm each step.
The command rm -rf removes files and directories recursively (-r) without any confirmation (-f = force). It executes instantly and cannot be undone.
Before using rm -rf, ALWAYS verify what will be deleted:
# STEP 1: See what will be affected
ls target-directory/
# STEP 2: Only after confirming the contents are correct
rm -rf target-directory/
Commands you must NEVER run:
rm -rf /-- Deletes every file on the entire systemrm -rf ~-- Deletes your entire home directory and all your workrm -rf *in the wrong directory -- Deletes everything in the current directory
The safe pattern: Use rm -i first to see what will be deleted. Once you've confirmed the target is correct, then use rm -rf if needed for speed.
Reading File Contents
Agents produce output: logs, reports, data files. You need to read these files without opening a graphical editor.
Reading Entire Files with cat
The cat command prints an entire file to the terminal:
cd ~/agents/customer-bot
echo "agent_name: customer-bot" > config/settings.yaml
echo "port: 8080" >> config/settings.yaml
echo "log_level: info" >> config/settings.yaml
cat config/settings.yaml
Output:
agent_name: customer-bot
port: 8080
log_level: info
cat is ideal for short files (under ~50 lines). For long files, it floods your terminal with text.
Reading the Beginning with head
The head command shows the first lines of a file. By default, it shows 10 lines. Use -n to specify how many:
# Create a longer file for demonstration
for i in $(seq 1 20); do echo "Log entry $i: Agent processed request" >> logs/agent.log; done
head -n 5 logs/agent.log
Output:
Log entry 1: Agent processed request
Log entry 2: Agent processed request
Log entry 3: Agent processed request
Log entry 4: Agent processed request
Log entry 5: Agent processed request
Reading the End with tail
The tail command shows the last lines of a file. This is especially useful for log files where the most recent entries are at the bottom:
tail -n 3 logs/agent.log
Output:
Log entry 18: Agent processed request
Log entry 19: Agent processed request
Log entry 20: Agent processed request
When debugging an agent, tail is usually your first command -- it shows you what happened most recently.
Scrolling Through Long Files with less
For files too long for cat but where you need to read more than just the beginning or end, use less:
less logs/agent.log
less opens the file in a scrollable viewer:
| Key | Action |
|---|---|
| Arrow keys | Scroll up/down line by line |
| Space | Scroll down one page |
| b | Scroll up one page |
| /search-term | Search forward for text |
| n | Jump to next search match |
| q | Quit and return to terminal |
less doesn't load the entire file into memory, so it works on files of any size -- even gigabyte log files from long-running agents.
When to Use Each Reading Command
| Command | Best For | Example |
|---|---|---|
cat | Short files (under 50 lines) | Config files, small scripts |
head -n N | Checking file format or headers | CSV headers, log format |
tail -n N | Recent log entries, latest errors | Agent debugging |
less | Exploring large files interactively | Full log analysis |
Wildcards and Globbing
When you manage multiple agents, each producing logs, configs, and data files, you need to work with groups of files at once. Wildcards let you match patterns instead of typing every filename.
The * Wildcard (Any Characters)
The * matches zero or more characters:
cd ~/agents/customer-bot/logs
touch agent.log error.log access.log debug.log
ls *.log
Output:
access.log agent.log debug.log error.log
You can use * anywhere in a pattern:
touch report-jan.csv report-feb.csv report-mar.csv summary.csv
ls report-*.csv
Output:
report-feb.csv report-jan.csv report-mar.csv
The pattern report-*.csv matched all files starting with report- and ending with .csv, excluding summary.csv.
The ? Wildcard (Single Character)
The ? matches exactly one character:
touch agent-1.log agent-2.log agent-3.log agent-10.log
ls agent-?.log
Output:
agent-1.log agent-2.log agent-3.log
Notice agent-10.log was not matched -- ? matches exactly one character, not two. This precision helps when you need to target specific file groups.
The [] Wildcard (Character Set)
Square brackets match any single character from a set:
ls agent-[12].log
Output:
agent-1.log agent-2.log
You can also specify ranges:
touch file-a.txt file-b.txt file-c.txt file-1.txt file-2.txt
ls file-[a-c].txt
Output:
file-a.txt file-b.txt file-c.txt
ls file-[0-9].txt
Output:
file-1.txt file-2.txt
Combining Wildcards
Wildcards combine to create precise patterns:
ls *-[0-9].log
Output:
agent-1.log agent-2.log agent-3.log
This matched any file ending in a single digit followed by .log.
Getting Help: man Pages and --help
When you encounter an unfamiliar command or need to check a specific flag, Linux has built-in documentation.
Quick Help with --help
Most commands support a --help flag that prints a usage summary:
cp --help
Output (abbreviated):
Usage: cp [OPTION]... SOURCE DEST
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
-r, -R, --recursive copy directories recursively
-i, --interactive prompt before overwrite
-v, --verbose explain what is being done
This gives you a fast reminder of available options without leaving your terminal.
Detailed Documentation with man
The man command opens the full manual page for any command:
man cp
This opens a detailed reference in less (the same viewer you learned earlier). Navigate with the same keys:
| Key | Action |
|---|---|
| Arrow keys | Scroll up/down |
| /pattern | Search for text |
| n | Next search match |
| q | Quit man page |
Man pages are organized into sections: NAME, SYNOPSIS, DESCRIPTION, OPTIONS, and EXAMPLES. When you need to understand a specific flag, search with / followed by the flag name (like /-r).
Exercises
Exercise 1: Build an Agent Workspace
Task: Create a complete workspace for an agent called customer-bot with subdirectories for source code, configuration, logs, and data.
mkdir -p ~/agents/customer-bot/{src,config,logs,data}
Verify your work:
ls -R ~/agents/customer-bot
Expected output:
/home/yourname/agents/customer-bot:
config data logs src
/home/yourname/agents/customer-bot/config:
/home/yourname/agents/customer-bot/data:
/home/yourname/agents/customer-bot/logs:
/home/yourname/agents/customer-bot/src:
You should see four subdirectories: config, data, logs, and src.
Exercise 2: Create, Copy, and Move Files
Task: Create a configuration file, copy it as a backup, then move the backup to a different directory.
cd ~/agents/customer-bot
echo "port: 8080" > config/app.yaml
cp config/app.yaml config/app.yaml.backup
mv config/app.yaml.backup data/
Verify your work:
ls config/ data/
Expected output:
config/:
app.yaml settings.yaml
data/:
app.yaml.backup settings.yaml
The original app.yaml stays in config/, while app.yaml.backup was copied then moved to data/.
Exercise 3: Wildcards in Action
Task: Create five numbered log files and use wildcards to list only those files.
cd ~/agents/customer-bot/logs
touch agent-1.log agent-2.log agent-3.log agent-4.log agent-5.log
Verify your work:
ls agent-*.log
Expected output:
agent-1.log agent-2.log agent-3.log agent-4.log agent-5.log
Now use the ? wildcard to match only single-digit agent logs:
ls agent-?.log
Expected output:
agent-1.log agent-2.log agent-3.log agent-4.log agent-5.log
All five match because each has exactly one character between agent- and .log.
Try With AI
Design an Agent Workspace:
I'm deploying 3 AI agents that each need directories for source code,
configuration, logs, and data. Design the directory structure and give
me the mkdir commands to create it all. The agents are:
1. customer-support-bot (handles tickets)
2. analytics-engine (processes data)
3. content-moderator (reviews submissions)
Also suggest what files would go in each directory.
What you're learning: Translating deployment requirements into filesystem structure. The AI can suggest organizational patterns you might not consider, like shared configuration directories or centralized log locations.
Understand Copy vs Move:
Explain the difference between cp and mv using a real-world analogy.
Then give me 3 specific scenarios for managing AI agent deployments
where I would use cp, and 3 where I would use mv. For each scenario,
show the exact command I would run.
What you're learning: Building judgment about when to duplicate files versus relocate them. In agent management, choosing wrong can mean losing your only copy of a configuration file or cluttering your workspace with unnecessary duplicates.
Recover from Mistakes:
I accidentally deleted an important configuration file with rm.
What are my recovery options on Linux? Also, what practices can
I adopt to prevent accidental deletions when managing agent files?
Give me specific commands and habits I should build.
What you're learning: Defensive file management practices. Linux doesn't have an undo button, so prevention strategies (aliases, backups, interactive mode defaults) are essential skills for anyone managing production agent deployments.