The command line has no recycle bin. Delete a file and it is unlinked immediately: no confirmation, no trash folder, no thirty day grace period. That fact scares people away from the four commands that do almost all the work of a working day. It should not. Learn how cp, mv, rm and ln behave, plus the two or three defaults that catch everyone in week one, and you can move data around a server faster than any file manager.
Here is the first thing Linux does that surprises newcomers. You try to copy a folder and it refuses:
$ cp project backup
cp: -r not specified; omitting directory 'project'
$ cp -r project backup
$ ls backup
README.md notes.txt src
That refusal is not a bug. cp copies one file by default, and a directory is a container of many files, so it makes you ask for the recursive copy on purpose. Once you see the pattern behind each command, the rest stops being scary.
Five commands cover most file work:
cp to copy, mv to move or rename, rm to delete, mkdir to make a folder, ln to link. The danger is not the commands, it is three quiet defaults: cp needs -r for folders, mv overwrites the target without asking, and rm deletes with no way back. Get those three into muscle memory and you are safe.This part is for two readers. If you are a college passout following along on a laptop, type every command yourself, because reading them does nothing. If you are already working in IT and just need the practical version, jump to the sections on rm safety and on hard versus symbolic links, which is where real incidents come from. Everything below runs the same on Ubuntu, Debian, and the RHEL family; the file tools are GNU coreutils on all of them.
The five verbs you will use every day
Before the deep end, here is the whole toolkit on one card. Keep it open in another tab for a week and you will not need it after that.
| Command | Does | Everyday example |
|---|---|---|
ls | List what is here | ls -lh |
cp | Copy a file, keep the original | cp app.conf app.conf.bak |
mv | Move or rename | mv draft.txt final.txt |
rm | Delete, no undo | rm old.log |
mkdir | Make a directory | mkdir -p a/b/c |
touch | Create an empty file, or bump its timestamp | touch notes.txt |
ln -s | Make a symbolic link | ln -s /opt/app/current app |
find | Search the tree by name, age, size | find . -name '*.log' |
Two quick ones before we slow down. mkdir -p a/b/c creates every missing parent in the path in one shot and does not complain if they already exist, which is why scripts use it constantly. touch file makes an empty file if none exists, and updates the modified time if it does. That timestamp trick matters later when you hunt for files by age.
Copying, and the directory trap
The grammar of cp is always the same: source first, destination last. cp a.txt b.txt makes b.txt a copy of a.txt. Add -r when the source is a folder. The flag you will reach for most is -a, the archive copy, which preserves permissions, ownership, and timestamps instead of stamping everything with the current time. When you back up a config directory, cp -a is almost always what you actually mean.
The default that bites: does the destination already exist?
Here is the single most confusing thing about copying folders, and it trips up people with years of experience. When you run cp -r src dest, the result depends on whether dest already exists.
Watch it happen. The second copy lands one level deeper than the first, and nothing warned you:
$ ls
src
$ cp -r src dest # dest did not exist
$ ls dest
file1 file2
$ cp -r src dest # now dest DOES exist
$ ls dest
file1 file2 src # src landed inside
If you meant to overwrite the contents rather than nest a folder, copy the contents with a trailing slash and a wildcard, or use cp -a src/. dest/, which copies what is inside src including hidden files. Two other flags are worth memorizing: -i asks before overwriting an existing file, and -n refuses to overwrite at all. On a shared server, cp -n is a cheap insurance policy.
Renaming is just moving
Linux has no separate rename command in daily use. mv does both jobs, because renaming a file is the same operation as moving it to a new name in the same directory. mv draft.txt final.txt renames. mv final.txt /home/dp/docs/ moves. mv across the same filesystem is instant no matter how large the file, because it only rewrites a directory entry; it does not copy bytes.
$ ls
report.txt report_final.txt
$ mv report_final.txt report.txt
$ ls
report.txt
Look closely at that sequence. The original report.txt is gone, silently overwritten by report_final.txt, and there was no prompt and no backup. This is the default that costs people real work.
A junior admin runs
mv new.conf app.conf to deploy an update and does not notice app.conf already held a hand tuned config nobody committed to version control. It is gone, and there is no copy. Two habits prevent this for good: use mv -i when you are not certain the target is empty, and pass mv --backup=numbered on anything that matters, which keeps the old file as app.conf.~1~ instead of destroying it.Deleting, with no net
When you rm a file, Linux removes the directory entry pointing to its data and, if that was the last entry, marks the space free. There is no trash folder on a plain server. Recovery means specialist tools and a lot of luck. So the mental model for rm is simple: whatever you name, assume it is gone the instant you press Enter.
$ ls
keep.conf old.log old.tmp
$ rm *.log *.tmp
$ ls
keep.conf
That worked because the shell expanded the wildcards before rm ever ran. You did not hand rm the text *.log; the shell replaced it with the matching filenames first, then ran the command. That expansion is the source of the most famous beginner disaster.
You mean to type
rm *.tmp but your finger adds a space: rm * .tmp. The shell expands the lone * to every file in the folder, and rm deletes all of them, then complains it cannot find a file literally named .tmp. The lesson is to read the whole line before Enter, and on anything destructive, run ls *.tmp first to preview exactly what the wildcard matches.A real opinion: do not alias rm to rm -i
Half the tutorials tell you to put alias rm='rm -i' in your shell config so every delete asks for confirmation. I think that advice does more harm than good, and I have seen why. It trains you to hit y without reading, because the prompt appears every single time even for a file you obviously want gone. Then you log into a production box that does not have your alias, muscle memory fires, and the safety you leaned on is not there. Better options: use rm -I, the capital variant from GNU coreutils, which prompts once before deleting three or more files or recursing into a directory, so it warns on the dangerous cases and stays quiet on the trivial ones. And on the truly important machines, slow your own hands down instead of outsourcing caution to a prompt you have taught yourself to ignore.
One more rule that has saved more servers than any alias: never run rm -rf with a variable in the path unless you are certain it is set. rm -rf $DIR/ becomes rm -rf / when DIR is empty. Quote your variables and check them first.
Hard links and symbolic links
A filename in Linux is not the file. The real file is an inode, a numbered record of the data and its permissions, and a name is just a label pointing at that inode. This is why links exist, and why the two kinds behave so differently. A hard link is a second name for the same inode. A symbolic link is a tiny separate file that holds a path, a signpost pointing at a name.
The difference is not academic. Watch what happens to each when the original name is deleted. The -i flag on ls prints the inode number in the first column, and the number after the permissions is the link count.
$ echo 'v1' > original.txt
$ ln original.txt hard.txt # hard link
$ ln -s original.txt soft.txt # symbolic link
$ ls -li
1234567 -rw-r--r-- 2 dp dp 3 Jul 3 09:14 hard.txt
1234567 -rw-r--r-- 2 dp dp 3 Jul 3 09:14 original.txt
1234570 lrwxrwxrwx 1 dp dp 12 Jul 3 09:14 soft.txt -> original.txt
$ rm original.txt # delete the first name
$ cat hard.txt
v1
$ cat soft.txt
cat: soft.txt: No such file or directory
Read the output carefully. original.txt and hard.txt share inode 1234567 and show a link count of 2, so they are genuinely the same file under two names. Deleting one name drops the count to 1 and the data survives under the other. The symlink has its own inode, 1234570, and points at the text original.txt; once that name is gone, the symlink dangles and points at nothing. Hard links cannot cross filesystems or point at directories; symlinks can do both, which is why symlinks are what you use in practice, for example to point /opt/app/current at whichever release directory is live.
Finding files without a mouse
Wildcards match names in one directory. When you need to search a whole tree by name, age, or size, that job belongs to find. Its grammar is a starting directory, then tests that narrow the results. find . -name '*.log' lists every log file under the current directory and everything below it. Quote the pattern so the shell hands the star to find instead of expanding it too early.
$ find . -name '*.log' -mtime +7
./var/app-2026-06-20.log
./var/app-2026-06-22.log
$ find . -name '*.log' -mtime +7 -delete
The -mtime +7 test means modified more than seven days ago, which is where the touch timestamp habit pays off. Always run the find once to see the list before you add -delete. On filesystems where other users can write, the GNU findutils manual recommends piping through xargs with null separators instead, because it handles spaces and odd characters in names safely:
$ find /var/tmp/stuff -mtime +90 -print0 | xargs -0 rm
The -print0 and xargs -0 pair separate filenames with a null byte, the one character that can never appear inside a path, so a file named with a space or a newline cannot break the command apart.
What is the difference between a hard link and a symbolic link, and what happens to each when you delete the original file? A strong answer: a hard link is another directory entry for the same inode, so the data survives as long as any hard link remains and deleting the original name is harmless. A symbolic link stores a path to a name, so it breaks the moment the target name disappears. Bonus points for adding that hard links cannot span filesystems or link directories, while symlinks can do both.
Prove the inode idea with your own hands. Make a folder, create a file, hard link it, and confirm both names share one inode and a link count of 2.
mkdir -p ~/lab && cd ~/labecho 'hello' > a.txtln a.txt b.txtVerify with exactly this:
stat -c '%h %i %n' a.txt b.txtYou should see the same inode number and a link count of 2 on both lines. Now run
rm a.txt then cat b.txt and watch the data survive.$ stat -c '%h %i %n' a.txt b.txt
2 1899024 a.txt
2 1899024 b.txt
Myth versus reality
Most beginner mistakes with these commands trace back to a handful of wrong assumptions. Here are the ones worth unlearning today.
| What people believe | What actually happens |
|---|---|
| rm sends files to a trash I can restore | There is no trash on a plain server. The data is unlinked at once and recovery is not something you can count on. |
| mv warns me before overwriting | It overwrites the target silently. Use mv -i or mv –backup to be warned or keep the old copy. |
| cp -r src dest always copies into dest | Only if dest already exists. If it does not, dest becomes the copy of src instead. |
| Deleting a file breaks its hard link | No. The data lives as long as any hard link remains, because they share one inode. |
| rm handles the wildcard itself | The shell expands the wildcard first. A stray space in rm * .tmp can wipe the whole folder. |
Copying, moving, and deleting are the commands you will run thousands of times, so the payoff from understanding their defaults now is enormous. Next in the series we move from handling files to controlling who is allowed to touch them, starting with users, groups, and the sudo command. If you want the wider map of where Linux sits next to the platforms it runs on, the Cloud for Beginners and VMware for Beginners guides cover the layers above it. Open a terminal, make a scratch folder, and break a few files on purpose. That is the fastest way to trust these commands.
References
GNU Coreutils: cp invocation
GNU Coreutils: ln invocation and link behavior
GNU Findutils: safely deleting files with find


DrJha