Linux - File Management Commands
Creating, copying, moving, renaming, and deleting files are daily operations on Linux. These six commands cover the vast majority of file management tasks.
mkdir — Make Directories
# Create a single directory
mkdir projects
# (creates projects/ in the current directory)
# Create a directory at an absolute path
mkdir /tmp/testdir
# Create nested directories in one command (-p flag)
mkdir -p projects/api/src/handlers
# Creates all missing parent directories
# Without -p, this would fail if projects/ didn't exist
# Create multiple directories at once
mkdir -p logs/{2024,2025}/{jan,feb,mar}
ls logs/
# 2024 2025
ls logs/2024/
# feb jan mar
# Create a directory and verify
mkdir -p ~/projects/myapp && ls -la ~/projects/
# Set permissions when creating (mode 755)
mkdir -m 755 /tmp/shared
ls -ld /tmp/shared
# drwxr-xr-x 2 ubuntu ubuntu 40 Apr 1 10:00 /tmp/shared
touch — Create Empty Files / Update Timestamps
# Create an empty file
touch notes.txt
ls -la notes.txt
# -rw-r--r-- 1 ubuntu ubuntu 0 Apr 1 10:00 notes.txt
# Create multiple files at once
touch file1.txt file2.txt file3.txt
# Create files in nested directories (directory must exist)
touch projects/api/main.go projects/api/go.mod
# Update the modification timestamp of an existing file (without changing content)
touch -m existing-file.txt
ls -la existing-file.txt
# -rw-r--r-- 1 ubuntu ubuntu 1234 Apr 1 10:05 existing-file.txt ← timestamp updated
# Common use case: trigger a build system that watches file timestamps
touch Makefile
cp — Copy Files and Directories
# Copy a file
cp source.txt destination.txt
# Copy a file to a directory (keeps original filename)
cp notes.txt ~/Documents/
# Creates ~/Documents/notes.txt
# Copy and rename at the same time
cp notes.txt ~/Documents/notes-backup.txt
# Copy a directory recursively (-r flag)
cp -r projects/ projects-backup/
# Copy with verbose output (shows what's being copied)
cp -rv projects/ projects-backup/
# 'projects/' -> 'projects-backup/'
# 'projects/api' -> 'projects-backup/api'
# 'projects/api/main.go' -> 'projects-backup/api/main.go'
# Preserve permissions, timestamps, and ownership (-p flag)
cp -p config.conf config.conf.bak
ls -la config.conf*
# -rw-r--r-- 1 ubuntu ubuntu 2048 Mar 15 08:00 config.conf
# -rw-r--r-- 1 ubuntu ubuntu 2048 Mar 15 08:00 config.conf.bak ← same timestamp
# Combine flags: recursive, preserve, verbose
cp -rpv /etc/nginx/ ~/nginx-backup/
# Interactive (-i): ask before overwriting existing files
cp -i new-version.conf config.conf
# cp: overwrite 'config.conf'? y
# Copy only if source is newer than destination (-u flag)
cp -u source.txt dest.txt
mv — Move and Rename Files
# Rename a file (move within the same directory)
mv oldname.txt newname.txt
# Move a file to another directory (keeps filename)
mv report.pdf ~/Documents/
# Move and rename in one step
mv report.pdf ~/Documents/annual-report-2025.pdf
# Move multiple files to a directory
mv file1.txt file2.txt file3.txt ~/Documents/
# Move a directory
mv projects/ ~/work/
# Rename a directory
mv old-project/ new-project/
# Interactive (-i): prompt before overwriting
mv -i source.txt existing-file.txt
# mv: overwrite 'existing-file.txt'? y
# Verbose output
mv -v *.log /var/log/archive/
# 'access.log' -> '/var/log/archive/access.log'
# 'error.log' -> '/var/log/archive/error.log'
Common pattern: backup before replacing:
# Backup the original, then replace
mv config.conf config.conf.bak
cp new-config.conf config.conf
rm — Remove Files and Directories
⚠️ Warning: Linux has no Recycle Bin. Files deleted with
rmare gone permanently. Always double-check before runningrm.
# Delete a single file
rm oldfile.txt
# Delete multiple files
rm file1.txt file2.txt file3.txt
# Delete files matching a pattern
rm *.log
rm temp-*
# Interactive (-i): confirm each deletion
rm -i important.txt
# rm: remove regular file 'important.txt'? y
# Recursive: delete a directory and all its contents (-r)
rm -r oldproject/
# Force: suppress error messages, never prompt (-f)
rm -f nonexistent-file.txt # No error even if file doesn't exist
# Dangerous combination: recursive force (-rf or -fr)
rm -rf /tmp/testdir/ # Be very careful with this
# NEVER do this (deletes the entire filesystem):
# rm -rf /
# Modern Linux has a --preserve-root protection:
rm -rf /
# rm: it is dangerous to operate recursively on '/'
# rm: use --no-preserve-root to override this failsafe
Safe rm patterns:
# 1. Always specify the full path
rm -rf /tmp/olddata/ # Good — specific path
rm -rf ./olddata/ # Good — explicit relative path
# 2. List what would be deleted before actually deleting
ls -la /tmp/olddata/ # Review first
rm -rf /tmp/olddata/ # Then delete
# 3. Use the trash-cli tool instead of rm for valuable files
sudo apt install trash-cli
trash file.txt # Moves to trash (recoverable)
trash-list # See what's in trash
trash-restore # Restore a file
trash-empty # Empty the trash permanently
# 4. Use a variable (but verify the variable isn't empty first!)
DIR_TO_DELETE="/tmp/mydata"
[[ -n "$DIR_TO_DELETE" ]] && rm -rf "$DIR_TO_DELETE"
ln — Create Links
Linux supports two types of links:
Hard Links
# A hard link is another name for the same file data (same inode)
ln original.txt hardlink.txt
ls -li
# 1048576 -rw-r--r-- 2 ubuntu ubuntu 1024 Apr 1 10:00 hardlink.txt
# 1048576 -rw-r--r-- 2 ubuntu ubuntu 1024 Apr 1 10:00 original.txt
# ↑ same inode number ↑ ↑ link count = 2
# Both names point to identical data
echo "hello" >> original.txt
cat hardlink.txt
# hello ← also updated
# Deleting original does NOT delete the data
rm original.txt
cat hardlink.txt
# hello ← data still accessible via hardlink
# Limitation: hard links cannot span filesystems or link to directories
Symbolic (Soft) Links
# A symlink is a pointer to another file's path (like a Windows shortcut)
ln -s /opt/myapp-v2.3.1/ /opt/myapp-current
ls -la /opt/
# drwxr-xr-x 5 ubuntu ubuntu 4096 Apr 1 10:00 myapp-v2.3.1
# lrwxrwxrwx 1 ubuntu ubuntu 18 Apr 1 10:00 myapp-current -> myapp-v2.3.1
# Access via the symlink
ls /opt/myapp-current/ # Same as ls /opt/myapp-v2.3.1/
# Upgrade pattern: update the symlink, not every config file
ln -sfn /opt/myapp-v2.4.0/ /opt/myapp-current
# -s = symbolic, -f = force (remove old), -n = treat dest as file not dir
# Verify where a symlink points
readlink /opt/myapp-current
# /opt/myapp-v2.3.1
readlink -f /opt/myapp-current # Resolve full absolute path
# /opt/myapp-v2.3.1
# Dangling symlink: points to a non-existent file
ln -s /tmp/doesnotexist /tmp/broken-link
ls -la /tmp/broken-link
# lrwxrwxrwx 1 ubuntu ubuntu 18 Apr 1 10:00 /tmp/broken-link -> /tmp/doesnotexist
cat /tmp/broken-link
# cat: /tmp/broken-link: No such file or directory ← dangling symlink
Practical Patterns
# Create a project scaffold in one go
mkdir -p myproject/{src,tests,docs,scripts}
touch myproject/{README.md,Makefile,.gitignore}
ls -R myproject/
# myproject/:
# Makefile README.md docs scripts src tests .gitignore
# Backup a config file before editing
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)
# Safely move all log files to archive
mkdir -p /var/log/archive
mv /var/log/app/*.log.gz /var/log/archive/
# Create a versioned symlink pattern
ln -sfn /opt/app-v1.2.0 /opt/app-current
ls -la /opt/app-current
# /opt/app-current -> /opt/app-v1.2.0
Key Takeaways
mkdir -pcreates nested directories in one command — use it alwayscp -rcopies directories; without-r,cponly copies filescp -ppreserves timestamps and permissions — important for backupsmvrenames and moves — no separate rename command in Linuxrmis permanent — always review withlsbeforerm -rf- Hard links share the same inode; symlinks are path pointers
- Symlinks are the standard way to implement versioned software (
/opt/app-current → /opt/app-v2.0)
| ← Back to Navigation Commands | Next → Viewing File Contents |