Linux gives you powerful file commands, but power requires care. A single rm -r in the wrong location can remove important data. The good news is that the core file operations are consistent and easy to learn once you practice them.
This lesson covers the commands you will use constantly in development, troubleshooting, and server administration.
Use mkdir to create directories.
mkdir project
mkdir -p project/config/environmentsThe -p flag creates parent directories as needed and does not fail if parts already exist.
Use touch to create an empty file or update a fileâs timestamp.
touch notes.txt
touch app.logTip:
mkdir -pis very common in automation because it is safe for repeated runs.
cpThe cp command copies files or directories.
cp app.conf app.conf.bak
cp -r site/ site-backup/
cp -v *.log archive/Useful flags:
-r copies directories recursively-v shows what is being copiedA common admin pattern is to back up a config before editing it:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bakmvThe mv command moves or renames files.
mv draft.txt final.txt
mv report.txt docs/If the target is a directory, the file is moved into it. If the target is a new filename in the same directory, the file is renamed.
rmThe rm command deletes files. It does not move them to a recycle bin.
rm old.log
rm -r old-directory
rm -i important.txtUseful flags:
-r removes directories recursively-i asks for confirmationNote: Many production mistakes start with removing the wrong path. Double-check with
pwdandlsbefore destructive commands.
catcat prints a fileâs full contents.
cat /etc/hosts
cat app.logIt is best for small files.
headhead shows the first lines of a file.
head app.log
head -n 20 app.logtailtail shows the last lines of a file.
tail app.log
tail -n 50 app.log
tail -f /var/log/nginx/access.logtail -f is especially useful for watching logs as new entries appear.
lessless lets you scroll through file contents interactively.
less /var/log/syslogUse the arrow keys or page navigation, type /error to search, and press q to quit.
The ln command creates links.
A hard link is another directory entry that points to the same underlying file data.
ln original.txt hardlink.txtBoth names refer to the same inode. Deleting one name does not remove the data as long as another hard link still exists.
A symbolic link or soft link points to another path.
ln -s /var/log/nginx/access.log access-current.logSymbolic links are more flexible because they can point across filesystems and to directories.
Tip: In DevOps, symbolic links are often used for versioned deployments, like linking
currentto the active release directory.
Suppose you are preparing a simple app directory:
mkdir -p myapp/{config,logs,bin}
touch myapp/config/app.conf
cp myapp/config/app.conf myapp/config/app.conf.bak
mv myapp/config/app.conf.bak myapp/config/app.conf.old
ln -s myapp/logs latest-logsYou created a structure, added a file, made a backup, renamed it, and created a symbolic link.
cp when you need a duplicatemv when you want to rename or relocaterm when you are sure you want permanent removalcat, head, tail, or less depending on file size and what part you needln -s when you want a flexible pointer to another pathBeginners often overuse cat for huge logs. On large files, less or tail is usually better.
Question: Which command from the lesson creates project/config/environments in one step without failing if parent directories are missing?
<MCQExercise exercise={{
id: 'linux-file-operations-q1',
title: 'Exercise 1: Creating directory trees',
description: 'Choose the mkdir form that safely creates nested parent directories.',
options: [
{ id: 'a', text: 'mkdir -p project/config/environments' },
{ id: 'b', text: 'touch -p project/config/environments' },
{ id: 'c', text: 'cp -r project/config/environments' },
{ id: 'd', text: 'rm -r project/config/environments' },
],
correctId: 'a',
explanation: 'The lesson highlights mkdir -p as the safe automation-friendly way to build nested directory structures. It creates any missing parent directories and does not complain if parts of the path already exist.',
wrongExplanations: {
b: 'touch creates files or updates timestamps. It does not build a nested directory tree.',
c: 'cp -r copies existing directories. It does not create a new hierarchy from nothing.',
d: 'rm -r removes directories rather than creating them.',
},
}} />
Scenario: You want to watch new Nginx access log lines appear during troubleshooting.
Question: Which command is the best match?
<MCQExercise exercise={{
id: 'linux-file-operations-q2',
title: 'Exercise 2: Following a growing file',
description: 'Identify the command that continues showing new lines added to a log file.',
options: [
{ id: 'a', text: 'head -n 50 /var/log/nginx/access.log' },
{ id: 'b', text: 'cat /var/log/nginx/access.log' },
{ id: 'c', text: 'tail -f /var/log/nginx/access.log' },
{ id: 'd', text: 'touch /var/log/nginx/access.log' },
],
correctId: 'c',
explanation: 'The tutorial calls out tail -f as the tool for following a log as new entries are appended. That live view is what makes it so useful during active debugging.',
wrongExplanations: {
a: 'head shows the beginning of a file once. It does not continue tracking appended lines.',
b: 'cat prints the current contents and exits. It is fine for small files, but it does not follow updates.',
d: 'touch creates a file or updates its timestamp. It does not display log content at all.',
},
}} />
Question: Why would ln -s be a good fit for a current release directory in a deployment?
<MCQExercise exercise={{
id: 'linux-file-operations-q3',
title: 'Exercise 3: Using flexible links',
description: 'Choose the reason symbolic links are useful in versioned deployments.',
options: [
{ id: 'a', text: 'A symbolic link stores a full duplicate copy of the target data.' },
{ id: 'b', text: 'A symbolic link points to another path, so current can be switched to a different release directory easily.' },
{ id: 'c', text: 'A symbolic link can only point to regular files in the same filesystem.' },
{ id: 'd', text: 'A symbolic link permanently merges two directories together.' },
],
correctId: 'b',
explanation: 'The tutorial explains that symbolic links are flexible path references and are often used to point current at the active release. Changing the link can redirect users to a new release without moving all the files.',
wrongExplanations: {
a: 'That would describe copying, not linking. A symlink references a path instead of duplicating file content.',
c: 'The lesson specifically notes that symbolic links can point across filesystems and to directories, so this restriction is incorrect.',
d: 'Symlinks do not merge directories. They simply provide a path that resolves to another location.',
},
}} />
rm has no undo and no trash. There is no recovery for an ordinary file.cp -r for directories, cp -a to preserve permissions, ownership and timestamps.cp and rsync behaviour: dir copies the directory, dir/ copies its contents.mv renames and moves with the same command; there is no separate rename.rm -i or an alias for interactive deletion rather than trusting yourself with -rf.less over cat for large files, and tail -F for one still being written.find -exec is powerful and unforgiving. Run it with -print first to see what it matches.-r copies a directory recursively but resets ownership to you and updates timestamps to now. -a (archive) preserves permissions, ownership, timestamps and symlinks, which is what you want when copying system files, a web root, or anything where metadata matters. A common symptom of using -r is a service refusing to start after a copy because files it needs are now owned by the wrong user. When in doubt on system files, use -a.
Almost always the trailing slash on the source. cp -a dir dest/ copies the directory itself, producing dest/dir; cp -a dir/. dest/ copies its contents into dest. rsync has the same distinction, where rsync -a src/ dest/ syncs contents and rsync -a src dest/ creates dest/src. The other cause is a destination that does not exist, in which case cp treats the last argument as a new filename rather than a directory.
find /path -name "*.log" matches by name, -iname case-insensitively, and -type f restricts to regular files. find /var -size +100M finds large files, and -mtime -7 those modified in the last week. Combine with -exec to act on results, find . -name "*.tmp" -delete, but always run the find alone first to see what it matches, because -delete and -exec rm are as unforgiving as rm itself. For searching contents rather than names, use grep -r or rg.
cat prints the whole file to your terminal, which is fine for something small and unhelpful for a 2 GB log. less pages through it without loading it all, supports / to search, and is the right default for anything large. head -n 20 shows the first lines and tail -n 50 the last, and tail -F follows a file as it grows, surviving log rotation, which the plain -f does not.
touch file.txt creates an empty file or updates an existing one's timestamp. mkdir -p a/b/c creates the whole path, creating parents as needed and succeeding silently if it already exists, which is what makes it safe in scripts, where plain mkdir errors on an existing directory. Brace expansion handles several at once: mkdir -p project/{src,tests,docs} creates all three subdirectories in one go.
Use grep, sed, awk, sort and uniq for real work: pick the right tool for each question, avoid the sed -i portability trap and see why errors vanish in pipes.
Understand Linux permissions: rwx for user, group and other, octal modes like 755 and 644, chmod versus chown, setuid, the sticky bit and umask defaults.
Manage Linux accounts safely: useradd versus adduser, why usermod -aG needs a new login, the destructive -G mistake, sudo versus su and the account files.