Introduction to chmod
The chmod (change mode) command is a fundamental Unix/Linux utility used to set and modify file and directory permissions. Understanding chmod is essential for system security, file sharing, and proper system operation.
Key Concepts
- File Permissions: Read (r), Write (w), Execute (x)
- User Classes: Owner (u), Group (g), Others (o)
- Numeric Mode: Permissions represented as octal numbers (e.g., 755, 644)
- Symbolic Mode: Permissions modified using symbols (e.g., u+x, go-w)
- Special Permissions: Setuid, Setgid, Sticky bit
1. Basic Concepts and Syntax
Understanding File Permissions
# View file permissions ls -l filename # Output: -rw-r--r-- 1 user group 1024 Mar 12 10:00 filename # ^^^^^^^ # |||||||| # |||||└── others permissions # ||||└── group permissions # |||└── owner permissions # |└── file type # └── permissions string # Permission breakdown # Position 1: File type (- = regular file, d = directory, l = symlink) # Positions 2-4: Owner permissions (rwx) # Positions 5-7: Group permissions (rwx) # Positions 8-10: Others permissions (rwx) # Example: -rwxr-xr-- # Owner: read, write, execute # Group: read, execute # Others: read only
Basic Syntax
# Basic syntax chmod [options] mode file # Numeric mode (octal) chmod 755 script.sh chmod 644 document.txt chmod 700 private/ # Symbolic mode chmod u+x script.sh # Add execute for owner chmod go-w document.txt # Remove write for group and others chmod a+r readme.txt # Add read for all (owner, group, others) # Recursive change chmod -R 755 directory/ chmod -R u+w directory/ # Verbose output chmod -v 644 file.txt # Show what changes are made
2. Numeric (Octal) Mode
Understanding Octal Permissions
# Octal values # Read (r) = 4 # Write (w) = 2 # Execute (x) = 1 # --- = 0 # Common combinations # 7 = 4+2+1 = rwx (read, write, execute) # 6 = 4+2 = rw- (read, write) # 5 = 4+1 = r-x (read, execute) # 4 = 4 = r-- (read only) # 3 = 2+1 = -wx (write, execute) # 2 = 2 = -w- (write only) # 1 = 1 = --x (execute only) # 0 = 0 = --- (no permissions) # Three-digit notation: owner-group-others chmod 754 file.txt # 7 (owner): rwx (4+2+1) # 5 (group): r-x (4+1) # 4 (others): r-- (4) # Four-digit notation: includes special permissions chmod 2755 script.sh # 2: setgid bit # 7: owner permissions # 5: group permissions # 5: others permissions
Common Octal Permissions
# Common permission sets chmod 600 file.txt # Owner: rw-, Group: ---, Others: --- (private file) chmod 644 file.txt # Owner: rw-, Group: r--, Others: r-- (default file) chmod 664 file.txt # Owner: rw-, Group: rw-, Others: r-- (shared file) chmod 700 file.txt # Owner: rwx, Group: ---, Others: --- (private executable) chmod 755 file.txt # Owner: rwx, Group: r-x, Others: r-x (default executable) chmod 777 file.txt # Owner: rwx, Group: rwx, Others: rwx (all access - DANGEROUS!) # Directory permissions chmod 755 directory/ # Owner: rwx, Group: r-x, Others: r-x (standard directory) chmod 700 directory/ # Owner: rwx, Group: ---, Others: --- (private directory) chmod 750 directory/ # Owner: rwx, Group: r-x, Others: --- (group directory) chmod 777 directory/ # Everyone can read/write/execute - DANGEROUS! # Special cases chmod 555 script.sh # Everyone can read/execute, no write chmod 000 file.txt # No permissions for anyone chmod 111 file.txt # Execute only for everyone
3. Symbolic Mode
Basic Symbolic Operations
# User classes # u = owner (user) # g = group # o = others # a = all (ugo) # Operations # + = add permission # - = remove permission # = = set exactly # Add permissions chmod u+x script.sh # Add execute for owner chmod g+w file.txt # Add write for group chmod o+r file.txt # Add read for others chmod a+x script.sh # Add execute for all # Remove permissions chmod u-x script.sh # Remove execute from owner chmod g-w file.txt # Remove write from group chmod o-r file.txt # Remove read from others chmod a-x script.sh # Remove execute from all # Set exact permissions chmod u=rwx script.sh # Set owner to rwx chmod g=rx script.sh # Set group to r-x chmod o=r script.sh # Set others to r-- chmod a=r file.txt # Set all to read-only # Multiple changes at once chmod u+rwx,g+rx,o+r script.sh chmod u=rwx,g=rx,o=r script.sh chmod ugo+x script.sh # Same as a+x
Advanced Symbolic Operations
# Copy permissions from one class to another
chmod g=u file.txt # Set group permissions equal to owner
chmod o=u file.txt # Set others permissions equal to owner
chmod o=g file.txt # Set others permissions equal to group
# Multiple changes with reference
chmod --reference=template.txt target.txt
# Recursive symbolic changes
chmod -R u+w directory/ # Add write for owner to all files/dirs
chmod -R go-w directory/ # Remove write for group/others
# Conditional changes (find + chmod)
find . -type f -exec chmod 644 {} \; # Set all files to 644
find . -type d -exec chmod 755 {} \; # Set all directories to 755
find . -name "*.sh" -exec chmod +x {} \; # Make all shell scripts executable
# Execute only if file is a directory
chmod u+X * # Add execute only for directories
4. Special Permissions
Setuid, Setgid, and Sticky Bit
# Special permission values (4-digit octal) # 4 = setuid (s/S) - user ID on execution # 2 = setgid (s/S) - group ID on execution # 1 = sticky (t/T) - restricted deletion # Setuid (user ID on execution) chmod 4755 script.sh # -rwsr-xr-x (setuid) chmod u+s script.sh # Symbolic form # Setgid (group ID on execution) chmod 2755 script.sh # -rwxr-sr-x (setgid) chmod g+s script.sh # Symbolic form # Sticky bit (restricted deletion) chmod 1777 /tmp # drwxrwxrwt (sticky bit) chmod +t /tmp # Symbolic form # Multiple special bits chmod 6755 script.sh # -rwsr-sr-x (setuid + setgid) chmod 7755 script.sh # -rwsr-sr-t (all special bits) # Display special permissions in ls ls -l /tmp # drwxrwxrwt ... # t indicates sticky bit # -rwsr-xr-x ... # s indicates setuid # -rwxr-sr-x ... # s indicates setgid
Practical Examples of Special Permissions
# Setuid example (for programs that need root privileges) sudo chmod 4755 /usr/bin/passwd # -rwsr-xr-x 1 root root ... /usr/bin/passwd # Setgid on directories (new files inherit group) chmod g+s shared_directory/ chmod 2755 shared_directory/ # Sticky bit on shared directories (only owner can delete) chmod +t /tmp chmod 1777 /tmp # Creating a shared group workspace mkdir /project chgrp projectgroup /project chmod 2775 /project # setgid + rwx for owner/group # Now all new files in /project inherit the 'projectgroup' group
5. Practical Examples
File Management Scripts
#!/bin/bash
# Set up a new project with proper permissions
setup_project() {
local project_dir="$1"
local group="${2:-developers}"
echo "Setting up project: $project_dir"
# Create directory structure
mkdir -p "$project_dir"/{src,docs,tests,bin}
# Set group ownership
chgrp -R "$group" "$project_dir"
# Set directory permissions
find "$project_dir" -type d -exec chmod 2775 {} \; # setgid + rwx for group
# Set file permissions
find "$project_dir" -type f -exec chmod 664 {} \; # rw for owner/group
# Make scripts executable
find "$project_dir/bin" -type f -exec chmod 775 {} \;
find "$project_dir" -name "*.sh" -exec chmod 775 {} \;
echo "Project setup complete"
ls -la "$project_dir"
}
# Secure home directory
secure_home() {
local home="${1:-$HOME}"
echo "Securing $home"
# Home directory should be 750 or 700
chmod 750 "$home"
# .ssh directory should be 700
if [ -d "$home/.ssh" ]; then
chmod 700 "$home/.ssh"
chmod 600 "$home/.ssh/"* 2>/dev/null
chmod 644 "$home/.ssh/"*.pub 2>/dev/null
fi
# Private files should be 600
find "$home" -name "*.key" -o -name "*.pem" -o -name "*secret*" \
-exec chmod 600 {} \; 2>/dev/null
echo "Security permissions applied"
}
# Fix permissions after copying from Windows
fix_permissions() {
local dir="${1:-.}"
echo "Fixing permissions in $dir"
# Directories: 755
find "$dir" -type d -exec chmod 755 {} \;
# Regular files: 644
find "$dir" -type f -not -name "*.sh" -not -name "*.pl" -not -name "*.py" \
-exec chmod 644 {} \;
# Scripts: 755
find "$dir" -name "*.sh" -o -name "*.pl" -o -name "*.py" -o -name "*.exe" \
-exec chmod 755 {} \;
echo "Permissions fixed"
}
Permission Checking and Validation
#!/bin/bash
# Check if file has specific permissions
check_permissions() {
local file="$1"
local required="$2" # e.g., "rwxr-xr-x"
current=$(ls -l "$file" | cut -c2-10)
if [ "$current" = "$required" ]; then
echo "✓ Permissions match"
return 0
else
echo "✗ Permissions mismatch"
echo " Required: $required"
echo " Current: $current"
return 1
fi
}
# Validate file is secure
validate_security() {
local file="$1"
perms=$(stat -c %a "$file")
owner=$(stat -c %U "$file")
if [ "$owner" != "$USER" ] && [ "$owner" != "root" ]; then
echo "⚠ File owned by $owner, not $USER"
fi
if [ -f "$file" ] && [ "$perms" -gt "644" ]; then
echo "⚠ File permissions too permissive: $perms"
fi
if [ -d "$file" ] && [ "$perms" -gt "755" ]; then
echo "⚠ Directory permissions too permissive: $perms"
fi
}
# Test if file is executable
is_executable() {
local file="$1"
if [ -x "$file" ]; then
echo "✓ $file is executable"
return 0
else
echo "✗ $file is not executable"
return 1
fi
}
# Check write permissions
check_writable() {
local file="$1"
if [ -w "$file" ]; then
echo "✓ Can write to $file"
else
echo "✗ Cannot write to $file"
fi
}
6. Recursive Operations
Recursive chmod Examples
# Change all files to 644, directories to 755
find /path -type f -exec chmod 644 {} \;
find /path -type d -exec chmod 755 {} \;
# Using xargs for better performance
find /path -type f -print0 | xargs -0 chmod 644
find /path -type d -print0 | xargs -0 chmod 755
# Make all shell scripts executable recursively
find . -name "*.sh" -exec chmod +x {} \;
# Add group write to all files in a directory
chmod -R g+w /shared/directory/
# Remove world read from everything
chmod -R o-r /private/directory/
# Set all files to read-only for group/others
chmod -R go-w,go-r ~/documents/
# Using find with complex conditions
find /project -type f -not -perm 644 -exec chmod 644 {} \;
find /project -type d -not -perm 755 -exec chmod 755 {} \;
Selective Recursive Changes
#!/bin/bash
# Recursively change permissions based on file type
smart_chmod() {
local dir="$1"
# Set directories to 755
find "$dir" -type d -exec chmod 755 {} \;
# Set regular files to 644
find "$dir" -type f \
-not -name "*.sh" \
-not -name "*.pl" \
-not -name "*.py" \
-not -perm -111 \
-exec chmod 644 {} \;
# Set executable files to 755
find "$dir" -type f \( \
-name "*.sh" -o \
-name "*.pl" -o \
-name "*.py" -o \
-name "*.bin" -o \
-perm /111 \) \
-exec chmod 755 {} \;
# Set configuration files to 600
find "$dir" -type f \( \
-name "*.conf" -o \
-name "*.cfg" -o \
-name "*.key" -o \
-name "*.pem" \) \
-exec chmod 600 {} \;
}
# Apply permissions with dry run
dry_run_chmod() {
local perms="$1"
local path="$2"
find "$path" -type f -print | while read file; do
current=$(stat -c %a "$file")
if [ "$current" != "$perms" ]; then
echo "Would change $file from $current to $perms"
fi
done
}
# Change permissions only on files owned by specific user
chown_user_chmod() {
local user="$1"
local perms="$2"
local path="$3"
find "$path" -user "$user" -exec chmod "$perms" {} \;
}
7. Scripting with chmod
Permission Functions
#!/bin/bash
# Function to get current permissions in octal
get_permissions() {
local file="$1"
stat -c %a "$file" 2>/dev/null || stat -f %A "$file" 2>/dev/null
}
# Function to get permissions in symbolic form
get_symbolic() {
local file="$1"
ls -l "$file" | awk '{print $1}'
}
# Save and restore permissions
save_permissions() {
local file="$1"
local savefile="${2:-/tmp/permissions.txt}"
echo "$file:$(get_permissions "$file")" >> "$savefile"
}
restore_permissions() {
local savefile="${1:-/tmp/permissions.txt}"
while IFS=: read file perms; do
if [ -e "$file" ]; then
chmod "$perms" "$file"
echo "Restored $file to $perms"
fi
done < "$savefile"
}
# Ensure minimum permissions
ensure_min_perms() {
local file="$1"
local min_perms="$2"
current=$(get_permissions "$file")
# Simple comparison (works for 3-digit octal)
if [ "$current" -lt "$min_perms" ] 2>/dev/null; then
echo "Increasing $file from $current to $min_perms"
chmod "$min_perms" "$file"
fi
}
Permission Validation Script
#!/bin/bash
# Comprehensive permission validator
validate_permissions() {
local path="$1"
local report_file="${2:-/tmp/perm_report.txt}"
{
echo "Permission Validation Report"
echo "============================"
echo "Path: $path"
echo "Date: $(date)"
echo
# Find files with world-writable permissions
echo "World-writable files:"
find "$path" -type f -perm -002 -ls 2>/dev/null | head -20
echo
# Find directories with world-writable (without sticky bit)
echo "World-writable directories (without sticky bit):"
find "$path" -type d -perm -002 -a ! -perm -1000 -ls 2>/dev/null | head -20
echo
# Find files with setuid/setgid
echo "Setuid/setgid files:"
find "$path" -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null | head -20
echo
# Find executable files owned by root
echo "Root-owned executable files:"
find "$path" -type f -user root -perm /111 -ls 2>/dev/null | head -20
echo
# Check home directory permissions
if [ -d "$HOME" ]; then
echo "Home directory permissions:"
ls -ld "$HOME"
fi
} > "$report_file"
echo "Report saved to $report_file"
}
# Quick security scan
security_scan() {
local critical_files=(
"/etc/passwd:644"
"/etc/shadow:600"
"/etc/ssh/sshd_config:600"
"/etc/sudoers:440"
)
for entry in "${critical_files[@]}"; do
file="${entry%%:*}"
expected="${entry#*:}"
if [ -f "$file" ]; then
current=$(stat -c %a "$file")
if [ "$current" != "$expected" ]; then
echo "⚠ $file has permissions $current (expected $expected)"
else
echo "✓ $file OK"
fi
fi
done
}
8. Integration with Other Commands
With find for Advanced Operations
# Find and fix files with incorrect permissions
find /var/www -type f -not -perm 644 -exec chmod 644 {} \;
find /var/www -type d -not -perm 755 -exec chmod 755 {} \;
# Make all newly created files group-writable
find /shared -type f -mtime -1 -exec chmod g+w {} \;
# Remove execute permission from all files except directories
find . -type f -exec chmod -x {} \;
# Add execute only to files that are already executable
find . -type f -perm /111 -exec chmod +x {} \;
# Complex permission fixes
find /project -type f \( \
-name "*.sh" -o \
-name "*.pl" -o \
-name "*.py" \) \
-exec chmod 755 {} \;
# Using -ok for confirmation
find . -name "*.conf" -ok chmod 644 {} \;
With chown and chgrp
# Combine ownership and permission changes
chown -R user:group directory/
chmod -R 755 directory/
# Set group and permissions together
chgrp -R developers /project
chmod -R 2775 /project
# Fix ownership and permissions for web files
chown -R www-data:www-data /var/www/
find /var/www -type f -exec chmod 644 {} \;
find /var/www -type d -exec chmod 755 {} \;
# User migration script
migrate_user() {
local old_user="$1"
local new_user="$2"
local dir="${3:-/home/$new_user}"
find "$dir" -user "$old_user" -exec chown "$new_user" {} \;
find "$dir" -group "$old_user" -exec chgrp "$new_user" {} \;
}
9. Troubleshooting and Error Handling
Common Issues and Solutions
#!/bin/bash
# Permission denied errors and fixes
fix_permission_denied() {
local file="$1"
if [ ! -e "$file" ]; then
echo "File does not exist: $file"
return 1
fi
if [ ! -r "$file" ]; then
echo "Adding read permission: $file"
chmod +r "$file"
fi
if [ ! -w "$file" ] && [ -d "$file" ]; then
echo "Adding write permission: $file"
chmod +w "$file"
fi
if [ -d "$file" ] && [ ! -x "$file" ]; then
echo "Adding execute permission to directory: $file"
chmod +x "$file"
fi
if [ -f "$file" ] && [ "${file##*.}" = "sh" ] && [ ! -x "$file" ]; then
echo "Making script executable: $file"
chmod +x "$file"
fi
}
# Debug permission issues
debug_permissions() {
local file="$1"
echo "=== Permission Debug: $file ==="
echo "Exists: $([ -e "$file" ] && echo "Yes" || echo "No")"
if [ -e "$file" ]; then
echo "Type: $([ -f "$file" ] && echo "File") $([ -d "$file" ] && echo "Directory")"
echo "Permissions: $(ls -l "$file" | awk '{print $1}')"
echo "Octal: $(stat -c %a "$file")"
echo "Owner: $(stat -c %U "$file")"
echo "Group: $(stat -c %G "$file")"
echo "Size: $(stat -c %s "$file")"
echo "Readable: $([ -r "$file" ] && echo "Yes" || echo "No")"
echo "Writable: $([ -w "$file" ] && echo "Yes" || echo "No")"
echo "Executable: $([ -x "$file" ] && echo "Yes" || echo "No")"
fi
}
Error Handling in Scripts
#!/bin/bash
# Safe chmod function
safe_chmod() {
local perms="$1"
local file="$2"
# Validate permissions format
if ! [[ "$perms" =~ ^[0-7]{3,4}$ ]] && ! [[ "$perms" =~ ^[ugoa]*[-+=][rwx]*$ ]]; then
echo "Error: Invalid permission format: $perms" >&2
return 1
fi
# Check if file exists
if [ ! -e "$file" ]; then
echo "Error: File not found: $file" >&2
return 1
fi
# Save original permissions
orig_perms=$(stat -c %a "$file" 2>/dev/null)
# Attempt to change permissions
if chmod "$perms" "$file" 2>/tmp/chmod_error.$$; then
echo "✓ Changed $file to $perms"
return 0
else
echo "✗ Failed to change $file permissions" >&2
cat /tmp/chmod_error.$$ >&2
rm /tmp/chmod_error.$$
return 1
fi
}
# Try to change permissions with escalation
chmod_with_escalation() {
local perms="$1"
local file="$2"
# Try normal
if chmod "$perms" "$file" 2>/dev/null; then
return 0
fi
# Try with sudo
if command -v sudo >/dev/null && sudo -n true 2>/dev/null; then
echo "Attempting with sudo..."
sudo chmod "$perms" "$file"
return $?
fi
echo "Failed to change permissions (try as root)" >&2
return 1
}
10. Advanced Techniques
ACL (Access Control Lists)
# Note: Requires ACL support # View ACL getfacl file.txt # Set ACL setfacl -m u:username:rwx file.txt setfacl -m g:groupname:rx file.txt # Remove ACL setfacl -x u:username file.txt # Recursive ACL setfacl -R -m u:username:rwx directory/ # Default ACL for new files setfacl -d -m u:username:rwx directory/
Umask and Default Permissions
# View current umask umask # Output: 0022 # Set umask (affects new files) umask 022 # Files: 644, Dirs: 755 umask 002 # Files: 664, Dirs: 775 umask 077 # Files: 600, Dirs: 700 # Calculate file permissions from umask # File base: 666 - umask # Dir base: 777 - umask # Set umask in scripts #!/bin/bash (umask 077 && touch private.txt) # Temporary umask change old_umask=$(umask) umask 077 touch secret.txt umask "$old_umask"
Mass Permission Changes
#!/bin/bash
# Change permissions for all files of certain types
mass_chmod() {
local pattern="$1"
local perms="$2"
local dir="${3:-.}"
find "$dir" -type f -name "$pattern" -exec chmod "$perms" {} \;
echo "Changed permissions for $pattern files to $perms"
}
# Normalize permissions in a directory tree
normalize_perms() {
local dir="$1"
echo "Normalizing permissions in $dir"
# Directories: 755
find "$dir" -type d -exec chmod 755 {} \;
# Regular files: 644
find "$dir" -type f -exec chmod 644 {} \;
# Executable files: 755
find "$dir" -type f -name "*.sh" -exec chmod 755 {} \;
# Config files: 640
find "$dir" -type f \( -name "*.conf" -o -name "*.cfg" \) -exec chmod 640 {} \;
# Private keys: 600
find "$dir" -type f \( -name "*.key" -o -name "*.pem" -o -name "*_rsa" \) \
-exec chmod 600 {} \;
}
# Batch permission report
permission_report() {
local dir="$1"
echo "Permission Report for $dir"
echo "=========================="
# Files with unusual permissions
echo "Files with non-standard permissions (not 644):"
find "$dir" -type f ! -perm 644 -ls 2>/dev/null | awk '{print $1, $11}' | head -20
echo -e "\nDirectories with non-standard permissions (not 755):"
find "$dir" -type d ! -perm 755 -ls 2>/dev/null | awk '{print $1, $11}' | head -20
}
11. Best Practices and Security
Security Guidelines
#!/bin/bash
# Security best practices
# 1. Never use 777 permissions
# 2. Use 755 for directories, 644 for files
# 3. Keep private files (ssh keys, passwords) at 600
# 4. Use sticky bit on shared directories
# 5. Be careful with setuid/setgid binaries
# Secure directory creation
secure_mkdir() {
local dir="$1"
mkdir -p "$dir"
chmod 750 "$dir"
}
# Secure file creation
secure_touch() {
local file="$1"
touch "$file"
chmod 600 "$file"
}
# Make script executable securely
secure_chmod_script() {
local script="$1"
if [ -f "$script" ] && [ -r "$script" ]; then
chmod 755 "$script"
echo "✓ Made $script executable (owner only write)"
fi
}
# Check for dangerous permissions
check_dangerous() {
local dir="${1:-/}"
echo "Scanning for dangerous permissions..."
# World-writable files
find "$dir" -type f -perm -002 2>/dev/null | while read file; do
echo "⚠ World-writable: $file"
done
# World-writable directories without sticky
find "$dir" -type d -perm -002 -a ! -perm -1000 2>/dev/null | while read dir; do
echo "⚠ Unsafe directory: $dir"
done
# Setuid root files
find "$dir" -type f -user root -perm -4000 2>/dev/null | while read file; do
echo "⚠ Setuid root: $file"
done
}
Production Environments
#!/bin/bash
# Web server permissions
setup_web_perms() {
local web_root="$1"
local web_user="${2:-www-data}"
local web_group="${3:-www-data}"
# Set ownership
chown -R "$web_user:$web_group" "$web_root"
# Directories: 755
find "$web_root" -type d -exec chmod 755 {} \;
# Files: 644
find "$web_root" -type f -exec chmod 644 {} \;
# Upload directories: 775
if [ -d "$web_root/uploads" ]; then
chmod 775 "$web_root/uploads"
fi
# Configuration files: 640
find "$web_root" -name "*.conf" -o -name "*.ini" -exec chmod 640 {} \;
}
# Database permissions
setup_db_perms() {
local db_dir="$1"
local db_user="${2:-mysql}"
chown -R "$db_user:$db_user" "$db_dir"
find "$db_dir" -type d -exec chmod 750 {} \;
find "$db_dir" -type f -exec chmod 640 {} \;
}
# Application deployment
deploy_app() {
local app_dir="$1"
local deploy_user="$2"
# Set base permissions
chown -R "$deploy_user:$(id -gn "$deploy_user")" "$app_dir"
find "$app_dir" -type d -exec chmod 755 {} \;
find "$app_dir" -type f -exec chmod 644 {} \;
# Make scripts executable
find "$app_dir" -name "*.sh" -o -name "*.pl" -o -name "*.py" \
-exec chmod 755 {} \;
# Secure configuration
find "$app_dir" -name "*.conf" -o -name "config.php" \
-exec chmod 640 {} \;
}
12. Command Summary and Cheat Sheet
Quick Reference
# Numeric mode examples chmod 644 file.txt # rw-r--r-- chmod 755 file.txt # rwxr-xr-x chmod 700 file.txt # rwx------ chmod 600 file.txt # rw------- chmod 777 file.txt # rwxrwxrwx (avoid!) # Symbolic mode examples chmod u+x file # Add execute for owner chmod go-w file # Remove write for group/others chmod a+r file # Add read for all chmod u=rwx,g=rx,o=r # Set specific permissions # Recursive operations chmod -R 755 dir/ chmod -R u+w dir/ # Special permissions chmod u+s file # Setuid chmod g+s dir # Setgid on directory chmod +t dir # Sticky bit # Common operations chmod +x script.sh # Make executable chmod -R g+w shared/ # Add group write chmod 700 ~/.ssh # Secure SSH directory chmod 600 ~/.ssh/id_rsa # Secure private key
Permission Quick Reference Table
# Numeric to Symbolic Conversion # 0 = --- # 1 = --x # 2 = -w- # 3 = -wx # 4 = r-- # 5 = r-x # 6 = rw- # 7 = rwx # Common Combinations # 400 = r-------- # 600 = rw------- # 644 = rw-r--r-- # 664 = rw-rw-r-- # 700 = rwx------ # 755 = rwxr-xr-x # 775 = rwxrwxr-x # 777 = rwxrwxrwx # Directory Permissions Meaning # r = can list contents # w = can create/delete files # x = can cd into directory
Permission Test Commands
# Test file permissions [ -r file ] && echo "Readable" [ -w file ] && echo "Writable" [ -x file ] && echo "Executable" # Test directory permissions [ -r dir ] && echo "Can list" [ -w dir ] && echo "Can create" [ -x dir ] && echo "Can access" # Compare permissions [ $(stat -c %a file1) = $(stat -c %a file2) ] && echo "Same permissions"
Conclusion
The chmod command is essential for system security and file management:
Key Takeaways
- Three User Classes: Owner (u), Group (g), Others (o)
- Three Permissions: Read (r=4), Write (w=2), Execute (x=1)
- Two Modes: Numeric (octal) and Symbolic
- Special Bits: Setuid (4), Setgid (2), Sticky (1)
- Security: Always use least-privilege principle
Best Practices Summary
| File Type | Recommended Permissions | Command |
|---|---|---|
| Regular files | 644 | chmod 644 file |
| Executable files | 755 | chmod 755 script |
| Private files | 600 | chmod 600 secret |
| Directories | 755 | chmod 755 dir |
| Shared directories | 775 | chmod 775 shared |
| SSH private keys | 600 | chmod 600 ~/.ssh/id_rsa |
| SSH public keys | 644 | chmod 644 ~/.ssh/*.pub |
| Web directories | 755 | chmod 755 /var/www/html |
Safety Rules
- Never use 777 on production systems
- Be careful with recursive changes - use
-Rcautiously - Always backup before mass permission changes
- Test with
-vto see what changes are made - Use
findfor selective permission changes - Regularly audit critical file permissions
- Set proper umask for new files
The chmod command, while simple in concept, requires careful consideration to maintain system security while ensuring proper functionality.