Recursive CHMOD: Setting Different Permissions for Files (660) vs Directories (770) in One Command


15 views

html

When managing permissions recursively, we often need different permission sets for directories (requiring execute bit) versus regular files. The standard chmod -R applies permissions uniformly, which creates security issues when directories need 770 but files should only have 660.

Here's the most efficient one-liner approach using GNU find:

find /path/to/base -type d -print0 | xargs -0 chmod 770
find /path/to/base -type f -print0 | xargs -0 chmod 660

For systems without xargs or with special characters in filenames:

find /path/to/base $-type d -exec chmod 770 {} +$ -o $-type f -exec chmod 660 {} +$

To prevent following symlinks (recommended for security):

find /path/to/base -type d -exec chmod 770 {} \; -exec chmod -h 770 {} \;
find /path/to/base -type f -exec chmod 660 {} \; -exec chmod -h 660 {} \;

After applying permissions, verify with:

find /path/to/base -type d -exec ls -ld {} \; | awk '{print $1,$9}'
find /path/to/base -type f -exec ls -l {} \; | awk 'NR<=20 {print $1,$9}'

Remember that new files/directories will inherit the umask settings. To maintain consistency, consider setting umask before creating new items:

# For directories
umask 007
mkdir new_directory

# For files
umask 117
touch new_file

When managing permissions recursively in UNIX/Linux systems, we often need distinct permission sets for directories and regular files. The standard chmod -R applies uniform permissions to all items, which creates security and functionality issues when directories need execute bits (for traversal) while files shouldn't.

A simple chmod -R 770 would:

  1. Give unnecessary execute permission to regular files
  2. Potentially break scripts expecting specific permission sets

Here's the most efficient one-liner solution:

find /path/to/directory -type d -exec chmod 770 {} \; -o -type f -exec chmod 660 {} \;

Breaking this down:

find /target/path       # Start search from this directory
-type d                 # Match directories
-exec chmod 770 {} \;   # Apply 770 to directories
-o                      # OR operator
-type f                 # Match regular files
-exec chmod 660 {} \;   # Apply 660 to files

For systems with many files, consider the + syntax for better performance:

find /path -type d -print0 | xargs -0 chmod 770
find /path -type f -print0 | xargs -0 chmod 660

Always verify changes with:

find /path -type d -ls | head -n 5   # Check first 5 directories
find /path -type f -ls | head -n 5   # Check first 5 files

A more modern approach using -execdir for better security:

find /path $-type d -execdir chmod 770 {} \;$ -o $-type f -execdir chmod 660 {} \;$

For a web server document root:

# Set directories to 770 (rwx for owner/group)
# Set files to 660 (rw for owner/group)
find /var/www/html -type d -exec chmod 770 {} \; -o -type f -exec chmod 660 {} \;

# Special handling for CGI scripts
find /var/www/cgi-bin -type f -exec chmod 770 {} \;