The Commands You Will Type More Than Any Others
Out of the 300-or-so commands a Linux engineer eventually learns, the ones that handle files and directories — ls, cd, cp, mv, rm, find, mkdir — are the ones you type ten thousand times a year. Knowing them deeply pays back constantly: muscle-memory commands save seconds; misuse loses files.
This article is a working reference for the file and directory commands every Linux user needs in their fingers, with the option flags that matter, the gotchas that bite, and the safer alternatives where they exist.
Where Am I? Where Do I Want To Go?
pwd # print working directory
cd /var/log # absolute path
cd ../etc # relative
cd ~ # home directory
cd - # back to previous directory
cd - is one of those quietly indispensable commands. It toggles between the last two directories you were in — useful when you’re bouncing between /etc/nginx and /var/log/nginx while debugging.
Listing Files: ls Is Not Just ls
ls # bare names
ls -l # long form: perms, owner, size, date
ls -la # include hidden (.) files
ls -lh # human-readable sizes (1.2M, 3.4G)
ls -ltr # by mtime, oldest first
ls -lS # by size, largest first
ls -ld /etc # the directory itself, not its contents
ls -1 # one entry per line (script-friendly)
Two patterns I use daily:
ls -ltrh— long-form, by time, oldest first, human sizes. The newest files are at the bottom (right where the prompt is).ls -lA | wc -l— count entries excluding.and..— a quick “how many things are in this directory.”
Creating: mkdir, touch
mkdir mydir # one directory
mkdir -p projects/2026/site # create whole path
touch newfile.txt # empty file (or update mtime)
touch -d "2025-01-15" report.txt # set explicit timestamp
install -d -m 0755 /opt/myapp/logs # create with permissions in one shot
mkdir -p is the right default. It silently no-ops if the directory exists and creates intermediate path components — ideal for scripts.
Copy: cp
cp source.txt dest.txt # single file
cp -r dir1/ dir2/ # recursive (directory)
cp -a backup/ /mnt/ # archive: preserve perms, timestamps, links
cp -i a b # interactive: prompt before overwrite
cp -u src/ dst/ # only newer files
Three behaviors people get wrong:
- Trailing slash on source matters.
cp -r dir/ /tmp/copies the contents ofdirinto/tmp/;cp -r dir /tmp/creates/tmp/dir/. Subtle and annoying. cp -ais what you usually want for full backups. Preserves attributes, follows links sensibly, recurses.cpoverwrites silently by default. Pair with-ifor interactive, or-nfor “no clobber.”
Move and Rename: mv
mv old.txt new.txt # rename
mv file.txt /tmp/ # move to another directory
mv -i old new # prompt before overwrite
rename 's/\.txt$/.md/' *.txt # bulk rename (Perl version)
There is no separate rename verb on Linux — mv handles both. The rename utility is much more powerful for batch renames; on Debian/Ubuntu it’s the Perl version (regex), on RHEL it’s a simpler util-linux version.
Delete: rm (Carefully)
rm file.txt # delete a file
rm -i *.log # interactive
rm -r dir/ # recursive (directory)
rm -rf dir/ # force, no prompt — irreversible
rm -- -filename # delete file whose name starts with dash
rm -rf is permanent. No trash, no recycle bin. Once it’s gone, you’re restoring from backup. Two safety habits:
- Never type
rm -rf $VAR/without first echoing$VARto verify it’s not empty. The day someone runsrm -rf /because$VARwas unset is the day someone learns about--no-preserve-rootthe hard way. - Use
find ... -printfirst, thenfind ... -delete. Verify the candidate file list before destroying it.
Find Things: find and locate
find /var/log -name "*.gz" # by name pattern
find / -type f -size +100M # files larger than 100MB
find . -mtime -7 # modified in last 7 days
find . -name "*.tmp" -delete # find AND delete (test with -print first)
find / -user alice -type f # files owned by alice
find /etc -name "*.conf" -exec grep -l "ssl" {} \;
locate nginx.conf # uses pre-built index (mlocate)
updatedb # rebuild the locate index
find is the heavyweight: live scan, infinite predicates. locate is the lightweight: instant lookup of a path index. The index is rebuilt nightly by cron — freshly created files won’t show up until the next updatedb run.
Symbolic Links
ln -s /usr/local/share/data /opt/data # symbolic link
ln -sf source target # force overwrite existing link
readlink /opt/data # read what a symlink points to
realpath /opt/data # resolve to absolute path
The order is always ln -s <target> <name-of-link>. People mix it up; the rule is “source first, then where you want the new pointer.”
The 10 Commands That Cover 95% of Daily Use
ls -ltrh— what’s here, sorted oldest-to-newestcd -— bounce between directoriescp -a src/ dst/— backup-style copymv old new— rename or relocatemkdir -p path/to/new— create paths idempotentlyfind / -name "file" 2>/dev/null— locate by name, suppress permission errorsdu -sh */— size of every subdirectory in the current dirln -sf src link— safely manage symbolic linksrm -- -strange— delete a file whose name starts with a dashtree -L 2— visual hierarchy (install if not present;treeis not in the base install)
Common Pitfalls
rm -rfwith an unset variable. Always echo first. Better:set -uin scripts so unset variables abort.- Trailing-slash confusion in
cp/rsync. Test on small data first. - Spaces in filenames. Quote everything:
cp "my file.txt" /tmp/— without quotes, that’s two arguments. - Forgetting
-ron directories.cp dir other/fails — needcp -r. - Locate is stale. Files newer than today’s
updatedbwon’t appear. Usefindfor current state. ls -laoutput parsed in scripts. Don’t. Usefindwith-printf, orstat, for machine-readable output.
Conclusion
Five habits that separate fluent Linux users from people who fight the shell:
- Aliases for what you type 10x a day —
alias ll='ls -ltrh'in~/.bashrc. - Tab-complete every path — mistyped paths cause 90% of file-op accidents.
- Echo before
rm -rf— always. - Quote filenames with spaces or special chars.
- Reach for
findnotls | grepwhen scripting — one is robust, the other breaks on weird filenames.
Related Linux Admin troubleshooting
For common errors and fixes related to this topic, see: