Linux - File Management Commands

5 minute read

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 rm are gone permanently. Always double-check before running rm.

# 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"

Linux supports two types of 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
# 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 -p creates nested directories in one command — use it always
  • cp -r copies directories; without -r, cp only copies files
  • cp -p preserves timestamps and permissions — important for backups
  • mv renames and moves — no separate rename command in Linux
  • rm is permanent — always review with ls before rm -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

Updated: