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.
Complete Bash Exercises with Solutions
Practice Bash scripting with solved exercises to improve your command-line and scripting skills.
Link: https://macronepal.com/complete-bash-exercises-with-solutions/
Complete Guide to Bash Crontab Command
Learn how to schedule and automate tasks efficiently using the Bash crontab command.
Link: https://macronepal.com/complete-guide-to-bash-crontab-command-schedule-tasks/
Complete Guide to Bash Arrays
Understand how to create, manage, and use arrays in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-arrays/
Bash Quiz: Test Your Knowledge
Test your Bash scripting knowledge with quizzes and practical questions.
Link: https://macronepal.com/bash-quiz-test-your-knowledge/
Complete Guide to Bash Functions
Learn how to write reusable Bash functions for cleaner and efficient scripts.
Link: https://macronepal.com/complete-guide-to-bash-functions/
Complete Guide to Bash Loops
Master loops in Bash for repetitive tasks and automation.
Link: https://macronepal.com/complete-guide-to-bash-loops/
Complete Guide to Bash If-Else Statements
Learn decision-making in Bash using conditional statements.
Link: https://macronepal.com/complete-guide-to-bash-ifelse-statements/
Complete Guide to Bash Operators
Explore arithmetic, logical, and comparison operators in Bash.
Link: https://macronepal.com/complete-guide-to-bash-operators/
Complete Guide to Bash Data Types
Understand variables and different data types used in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-data-types/
Complete Guide to Bash Variables
Learn how to declare, assign, and use variables in Bash scripts.
Link: https://macronepal.com/complete-guide-to-bash-variables/
Complete Guide to Bash Scripting
A complete introduction to writing Bash scripts for automation.
Link: https://macronepal.com/complete-guide-to-bash-scripting/
Complete Guide to Basic Bash Syntax
Learn the fundamental syntax needed to write Bash commands and scripts.
Link: https://macronepal.com/complete-guide-to-basic-bash-syntax/
Complete Guide to Bash Chgrp Command
Learn how to change group ownership of files and directories.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership-2/
Complete Guide to Bash Chgrp Command (Alternate)
Another detailed explanation of Bash group ownership management.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership/
Complete Guide to Bash File Permissions and Ownership
Understand Linux file permissions and ownership management.
Link: https://macronepal.com/complete-guide-to-bash-file-permissions-and-ownership/
Complete Guide to Bash Chmod Command
Learn how to modify file permissions using chmod.
Link: https://macronepal.com/complete-guide-to-bash-chmod-command-change-file-permissions/
Complete Guide to Bash Chown Command
Change file ownership using the Bash chown command.
Link: https://macronepal.com/complete-guide-to-bash-chown-command-change-file-ownership/
Complete Guide to Bash SCP Command
Securely transfer files between systems using SCP.
Link: https://macronepal.com/complete-guide-to-bash-scp-command-secure-copy/
Complete Guide to Bash SSH Command
Learn secure remote access and server management using SSH.
Link: https://macronepal.com/complete-guide-to-bash-ssh-command/
Bash Wget Command Complete Guide
Download files from the internet using the wget command.
Link: https://macronepal.com/bash-wget-command-complete-guide-to-non-interactive-network-downloader/
