File_ops
Chapter 18: File Operations in Bash
Section titled “Chapter 18: File Operations in Bash”Overview
Section titled “Overview”This chapter covers file operations in Bash - a critical skill for DevOps engineers and system administrators. File operations are the backbone of automation scripts, configuration management, log processing, and backup solutions.
Understanding Files in Linux
Section titled “Understanding Files in Linux”What is a File?
Section titled “What is a File?”In Linux, everything is a file:
- Regular files (
-) - Directories (
d) - Symbolic links (
l) - Character devices (
c) - Block devices (
b) - Named pipes (
p) - Sockets (
s)
File Descriptors
Section titled “File Descriptors”Linux uses file descriptors (FD) to access files:
| FD Number | Name | Default Destination |
|---|---|---|
| 0 | stdin | Keyboard |
| 1 | stdout | Terminal |
| 2 | stderr | Terminal |
Reading Files
Section titled “Reading Files”Method 1: Using cat
Section titled “Method 1: Using cat”The simplest way to read a file:
# Display entire filecat /etc/hostname
# Display with line numberscat -n /etc/hostname
# Display with line numbers (non-empty lines)cat -b /etc/hostname
# Show $ at end of lines (useful for debugging whitespace)cat -A /etc/hostnameReal-world DevOps Example:
# View configuration filecat /etc/nginx/nginx.conf
# Check application configcat /var/www/html/app/config.phpMethod 2: Using less (Recommended for Large Files)
Section titled “Method 2: Using less (Recommended for Large Files)”# Open file for viewing (large files)less /var/log/syslog
# Common less commands:# /search - Search forward# ?search - Search backward# n - Next match# N - Previous match# g - Go to beginning# G - Go to end# q - Quit# -N - Show line numbers
# Practical examplesless +G /var/log/messages # Start at end of fileless -N /var/log/syslog # Show line numbersless -S /var/log/nginx.log # Don't wrap long linesMethod 3: Using head
Section titled “Method 3: Using head”Display the first lines of a file:
# First 10 lines (default)head /var/log/syslog
# First N lineshead -n 20 /var/log/syslog
# First N byteshead -c 1KB /var/log/syslog
# DevOps exampleshead -1 /etc/passwd # Show first userhead -n 100 /var/log/nginx/access.log # First 100 requestsMethod 4: Using tail
Section titled “Method 4: Using tail”Display the last lines of a file:
# Last 10 lines (default)tail /var/log/syslog
# Last N linestail -n 20 /var/log/syslog
# Last N bytestail -c 500 /var/log/syslog
# Follow file in real-time (critical for monitoring)tail -f /var/log/syslogtail -f /var/log/nginx/error.log
# Follow with specific linestail -f -n 100 /var/log/app.log
# DevOps Examplestail -f /var/log/auth.log # Monitor login attemptstail -f /var/log/nginx/access.log # Monitor live traffictail -n 50 /var/log/docker.log # Recent Docker eventsMethod 5: Using awk for Selective Reading
Section titled “Method 5: Using awk for Selective Reading”# Print specific columnsawk '{print $1, $5}' /var/log/nginx/access.log
# Print lines matching patternawk '/ERROR/ {print}' /var/log/app.log
# Print specific line numbersawk 'NR==10 {print}' /var/log/syslog
# Print first and last fieldawk '{print $1, $NF}' /etc/passwdMethod 6: Using sed for Line Selection
Section titled “Method 6: Using sed for Line Selection”# Print specific linesed -n '5p' /etc/passwd
# Print range of linessed -n '5,10p' /etc/passwd
# Print every Nth linesed -n '~5p' /var/log/syslog # Every 5th lineWriting and Appending to Files
Section titled “Writing and Appending to Files”Redirect Output to New File
Section titled “Redirect Output to New File”# Create new file (overwrites existing)echo "Hello World" > /tmp/output.txtcat /etc/hostname > /tmp/hostname.txt
# Using printf for more controlprintf "%s\n" "Line 1" "Line 2" "Line 3" > /tmp/output.txtAppend to Existing File
Section titled “Append to Existing File”# Append to file (creates if not exists)echo "New line" >> /tmp/output.txt
# Append multiple linescat >> /tmp/log.txt <<EOF$(date) - Application started$(date) - Health check passed$(date) - Backup completedEOFWriting with tee
Section titled “Writing with tee”The tee command writes to both file and stdout:
# Write and displayecho "Logging this" | tee /var/log/app.log
# Append and displayecho "New entry" | tee -a /var/log/app.log
# Tee to multiple filesecho "Data" | tee file1.txt file2.txt file3.txt
# Suppress stdoutecho "Silent log" | tee -s /var/log/app.logReal-world DevOps Example:
#!/usr/bin/env bash# Automated log rotation and archiving
LOG_FILE="/var/log/app/application.log"ARCHIVE_DIR="/var/log/archive"TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Create archive directorymkdir -p "$ARCHIVE_DIR"
# Archive current logcat "$LOG_FILE" | tee "$ARCHIVE_DIR/app_$TIMESTAMP.log"
# Truncate log file> "$LOG_FILE"
echo "Log archived to $ARCHIVE_DIR/app_$TIMESTAMP.log"File Information and Metadata
Section titled “File Information and Metadata”stat - Detailed File Information
Section titled “stat - Detailed File Information”# Basic stat outputstat /etc/hostname
# Custom formatstat -c '%n is %s bytes' /etc/hostnamestat -c 'Modified: %y' /etc/hostnamestat -c 'Access: %x, Modify: %y, Change: %z' /etc/hostname
# Stat multiple filesstat /etc/passwd /etc/hostname
# Check file typestat -c '%A (%a) - %F' /etc/hostnameFormat specifiers:
%n- File name%s- Size in bytes%A- Permissions in human form%a- Permissions in octal%F- File type%x- Last access time%y- Last modification time%z- Last change time
file - Determine File Type
Section titled “file - Determine File Type”# Basic file typefile /etc/hostnamefile /bin/lsfile /var/log/syslog
# Don't pause for "file" commandfile -s /dev/sda1
# Show MIME typefile -i /etc/passwd
# Multiple filesfile /etc/*File Permissions
Section titled “File Permissions”Understanding Permissions
Section titled “Understanding Permissions”Permission Structure: drwxr-xrwx| | | | | | || | | | | | +-- Others: rwx (7)| | | | | +----- Group: rwx (7)| | | | +---------- Owner: rwx (7)| | | +------------- Directory marker+--+--+---------------- Type (d=dir, -=file, l=link)Numeric Permissions
Section titled “Numeric Permissions”| Number | Permission | Binary |
|---|---|---|
| 0 | --- | 000 |
| 1 | —x | 001 |
| 2 | -w- | 010 |
| 3 | -wx | 011 |
| 4 | r— | 100 |
| 5 | r-x | 101 |
| 6 | rw- | 110 |
| 7 | rwx | 111 |
Common Permission Sets
Section titled “Common Permission Sets”# 755 - Standard for executables and directories# rwxr-xr-x
# 644 - Standard for regular files# rw-r--r--
# 600 - Private files (owner only)# rw-------
# 700 - Private directories# rwx------
# 777 - World writable (AVOID!)# rwxrwxrwxchmod - Change Permissions
Section titled “chmod - Change Permissions”# Symbolic modechmod u+x script.sh # Add execute for ownerchmod g-w file.txt # Remove write for groupchmod o=rw file.txt # Set others to read/writechmod a+x script.sh # Add execute for allchmod +x script.sh # Add execute for all (same)
# Numeric modechmod 755 script.sh # rwxr-xr-xchmod 644 config.txt # rw-r--r--chmod 600 .env # rw-------chmod 700 /secret/dir # rwx------
# Recursivechmod -R 755 /webapp # All files in directorychmod -R +X /webapp # Only directories and add executechown - Change Ownership
Section titled “chown - Change Ownership”# Change ownerchown user file.txt
# Change owner and groupchown user:group file.txt
# Change group onlychown :group file.txt
# Recursivechown -R nginx:nginx /var/www
# Change owner of symbolic link (not target)chown -h user link.txtSearching for Files
Section titled “Searching for Files”find - The Power Tool
Section titled “find - The Power Tool”# Find by namefind /etc -name "*.conf"find /var -name "*.log"
# Case insensitivefind /etc -iname "*.Conf"
# Find by typefind / -type f # Regular filesfind / -type d # Directoriesfind / -type l # Symbolic linksfind / -type b # Block devices
# Find by timefind /var/log -mtime -7 # Modified in last 7 daysfind /var/log -mtime +30 # Modified more than 30 days agofind /var/log -atime -1 # Accessed in last 24 hoursfind /var/log -ctime -1 # Changed in last 24 hours
# Find by sizefind / -size +100M # Files larger than 100MBfind / -size -1K # Files smaller than 1KBfind / -size 0 # Empty files
# Find by permissionsfind / -perm 644 # Exactly 644find / -perm -644 # At least 644 (includes 755)find / -perm /u=x # Owner executable
# Find and executefind /var/log -name "*.log" -exec wc -l {} \;find /etc -name "*.conf" -exec grep "Listen" {} \;
# Find and deletefind /tmp -type f -mtime +7 -delete
# Find and archivefind /var/www -name "*.php" -exec tar -czf php_files.tar.gz {} +Real-world DevOps Examples:
# Find large log filesfind /var/log -type f -size +100M
# Find configuration filesfind /etc -name "*.conf" -o -name "*.cfg"
# Find files modified in last hourfind /var/www/html -type f -mmin -60
# Find executable scriptsfind /opt -type f -perm -u+x
# Find and change ownershipfind /var/www -type f -exec chown www-data:www-data {} \;
# Find files owned by specific userfind / -user nginx -type flocate - Fast File Search
Section titled “locate - Fast File Search”# Install mlocate first (sudo pacman -S mlocate)sudo updatedb
# Quick search (uses database)locate nginx.conflocate -i readme # Case insensitive
# Limit resultslocate -n 20 "*.log"
# Only existing fileslocate -e "*.conf"which - Find Command Location
Section titled “which - Find Command Location”# Find command pathwhich python3which kubectlwhich docker
# Find all occurrenceswhich -a python3whereis - Find Binary, Source, Manual
Section titled “whereis - Find Binary, Source, Manual”whereis python3# python3: /usr/bin/python3 /usr/share/man/man1/python3.1.gzFile Comparison
Section titled “File Comparison”diff - Compare Files
Section titled “diff - Compare Files”# Compare two filesdiff file1.txt file2.txt
# Side-by-side comparisondiff -y file1.txt file2.txt
# Unified diff (git style)diff -u file1.txt file2.txt
# Ignore casediff -i file1.txt file2.txt
# Ignore whitespacediff -w file1.txt file2.txt
# Recursive directory comparisondiff -r dir1/ dir2/cmp - Binary Comparison
Section titled “cmp - Binary Comparison”# Quick comparisoncmp file1.txt file2.txt
# Silent (exit code only)cmp -s file1.txt file2.txt && echo "Identical"comm - Line-by-Line Comparison
Section titled “comm - Line-by-Line Comparison”# Compare sorted filescomm file1.txt file2.txt
# Only lines unique to file1comm -23 file1.txt file2.txt
# Only lines unique to file2comm -13 file1.txt file2.txt
# Only common linescomm -12 file1.txt file2.txtFile Compression
Section titled “File Compression”tar - Archive Files
Section titled “tar - Archive Files”# Create archivetar -cf archive.tar file1 file2 dir1/tar -cvf archive.tar file1 file2 # Verbose
# Extract archivetar -xf archive.tartar -xvf archive.tar # Verbose
# List contentstar -tf archive.tar
# Create gzipped archive (most common)tar -czvf archive.tar.gz dir1/tar -czf archive.tar.gz dir1/
# Extract gzippedtar -xzvf archive.tar.gztar -xzf archive.tar.gz
# Create bz2 archivetar -cjvf archive.tar.bz2 dir1/
# Create xz archive (best compression)tar -cJvf archive.tar.xz dir1/
# Extract to specific directorytar -xf archive.tar -C /destination/
# Extract specific filetar -xf archive.tar specific_file.txt
# Add to existing archivetar -rf archive.tar newfile.txt
# Update existing archivetar -uf archive.tar modified_file.txtgzip / gunzip
Section titled “gzip / gunzip”# Compress filegzip file.txt# Results in file.txt.gz
# Keep originalgzip -k file.txt
# Compress to stdoutgzip -c file.txt > file.txt.gz
# Decompressgunzip file.txt.gzgzip -d file.txt.gz
# View without extractingzcat file.txt.gzzless file.txt.gzzgrep "pattern" file.txt.gzzip / unzip
Section titled “zip / unzip”# Create zip archivezip archive.zip file1 file2
# Recursivezip -r archive.zip directory/
# Exclude fileszip -r archive.zip directory/ -x "*.git/*"
# Extractunzip archive.zip
# Extract to directoryunzip archive.zip -d /destination/
# List contentsunzip -l archive.zip
# Password protectzip -P password archive.zip file.txtFile Editing
Section titled “File Editing”sed for In-Place Editing
Section titled “sed for In-Place Editing”# Replace text in file (macOS requires empty string for backup)sed -i 's/old/new/g' file.txt
# Create backup before editingsed -i.bak 's/old/new/g' file.txt
# Delete lines matching patternsed -i '/pattern/d' file.txt
# Insert line before patternsed -i '/pattern/i\New line' file.txt
# Append line after patternsed -i '/pattern/a\New line' file.txtUsing vim/nano for Interactive Editing
Section titled “Using vim/nano for Interactive Editing”# Open with vimvim file.txtnano file.txt
# Non-interactive editingex -s +'%s/old/new/g' +wq file.txtWorking with Directories
Section titled “Working with Directories”mkdir - Create Directories
Section titled “mkdir - Create Directories”# Basicmkdir newdir
# Create parent directoriesmkdir -p /path/to/nested/dir
# Create with permissionsmkdir -m 755 newdir
# Verbosemkdir -pv newdirrmdir - Remove Empty Directories
Section titled “rmdir - Remove Empty Directories”# Basicrmdir emptydir
# Remove parent if emptyrmdir -p parent/childrm - Remove Files and Directories
Section titled “rm - Remove Files and Directories”# Remove filerm file.txt
# Remove directory and contentsrm -rf directory/
# Interactiverm -i file.txt
# Verboserm -rv directory/
# Force (no prompts)rm -f file.txt
# Preserve root (safety)rm -rf / # DON'T DO THIS!Special File Operations
Section titled “Special File Operations”touch - Create Empty File / Update Timestamp
Section titled “touch - Create Empty File / Update Timestamp”# Create empty filetouch newfile.txt
# Update timestamptouch existingfile.txt
# Create with specific timestamptouch -d "2024-01-01 00:00:00" file.txttouch -t 202401010000 file.txt
# Create multiple filestouch file{1..10}.txtln - Create Links
Section titled “ln - Create Links”# Hard linkln source.txt hardlink.txt
# Symbolic (soft) linkln -s source.txt symlink.txt
# Symbolic link to directoryln -s /var/www/html website
# Update linkln -sf newtarget symlinkcp - Copy Files
Section titled “cp - Copy Files”# Copy filecp source.txt destination.txt
# Copy to directorycp file.txt /destination/
# Preserve attributescp -p file.txt /destination/
# Recursivecp -r directory/ /destination/
# Interactive (ask before overwrite)cp -i file.txt /destination/
# Update (only if newer)cp -u file.txt /destination/
# Archive (preserves everything)cp -a source/ destination/mv - Move/Rename Files
Section titled “mv - Move/Rename Files”# Move filemv source.txt /destination/
# Rename filemv oldname.txt newname.txt
# Move and renamemv source.txt /destination/newname.txt
# Interactivemv -i source.txt /destination/
# Force (no prompts)mv -f source.txt /destination/Summary
Section titled “Summary”In this chapter, you learned:
- ✅ Reading files with cat, less, head, tail
- ✅ Writing and appending to files
- ✅ Using tee for logging
- ✅ Understanding file metadata with stat
- ✅ File permissions (chmod, chown)
- ✅ Finding files (find, locate, which)
- ✅ File comparison (diff, cmp, comm)
- ✅ File compression (tar, gzip, zip)
- ✅ File editing (sed, vim)
- ✅ Directory operations
- ✅ Links, copy, move operations
Next Steps
Section titled “Next Steps”Continue to the next chapter to learn about Here Documents and Here Strings.
Previous Chapter: Arguments Next Chapter: Here Documents