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


6 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 {} \;