Skip to main content
Updated Feb 16, 2026

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.

rm -rf: The Most Dangerous Command in Linux

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 system
  • rm -rf ~ -- Deletes your entire home directory and all your work
  • rm -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:

KeyAction
Arrow keysScroll up/down line by line
SpaceScroll down one page
bScroll up one page
/search-termSearch forward for text
nJump to next search match
qQuit 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

CommandBest ForExample
catShort files (under 50 lines)Config files, small scripts
head -n NChecking file format or headersCSV headers, log format
tail -n NRecent log entries, latest errorsAgent debugging
lessExploring large files interactivelyFull 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:

KeyAction
Arrow keysScroll up/down
/patternSearch for text
nNext search match
qQuit 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.