Linux / UNIX: Change File Permissions Recursively ( conditional )

How do I recursively change files with 777 permissions to 755 in /home/user/demo directory? I have a number of files in this directory and I need to change permission from 0777 to only if that file has 777 permissions. Is there an easy way out to achieve this on a Linux or Unix-like systems?

To change file access permissions you need to use the chmod command. It has -R or –recursive option that change files and directories recursively. [donotprint]
Tutorial details
DifficultyEasy (rss)
Root privilegesNo
RequirementsNone
Time2m
[/donotprint]The find command can be used to find files and directories. The chown command can be used to change user and group permission.

ADVERTISEMENTS

chmod Command Examples

In this example, you are setting permission to 0755:
$ chmod -R 0755 directoryNameHere
However, if you need to apply conditional file permissions recursively, you need to use combination of the find and chmod command. To find all files in /home/user/demo directory, enter:
$ find /home/user/demo -type f -print
To find all files in /home/user/demo directory with permission 777, enter:
$ find /home/user/demo -type f -perm 777 -print
Finally, apply new permission using the -exec option as follows:
$ find /home/user/demo -type f -perm 777 -print -exec chmod 755 {} \;
To select directories and subdirectories use the following syntax:

$ find /var/www/html -type d -perm 777 -print -exec chmod 755 {} \;

Sample Shell Script To Change Permission Recursively

#!/bin/bash
# Purpose: Set correct webserver files and dir permissions
# Author: Vivek Gite < vivek@nixcraft.com >
# This script is released under GPL version 2.0 or above
# Set root permission as follows for the Apache / Lighttpd / Nginx DocumentRoot
# + Dirs/Subdirs: read-only and execute to others
# + Files: read-only permission
# Tested on Debian Linux v3/4/5/6 and RHEL v2/3/4/5/6
# -------------------------------------------------------------------------------------------------
_dir="${1:-.}"
_fperm="0444"
_dperm="0445"
_ugperm="root:root"
_chmod="/bin/chmod"
_chown="/bin/chown"
_find="/usr/bin/find"
_xargs="/usr/bin/xargs"
 
echo "I will change the file permission for webserver dir and files to restrctive read-only mode for \"$_dir\""
read -p "Your current dir is ${PWD}. Are you sure (y / n) ?" ans
if [ "$ans" == "y" ]
then
	echo "Changing file onwership to $_ugperm for $_dir..."
	$_chown -R "${_ugperm}" "$_dir"
 
	echo "Setting $_fperm permission for $_dir directory...."
	$_chmod -R "${_fperm}" "$_dir"
 
	echo "Setting $_dperm permission for $_dir directory...."
	$_find "$_dir" -type d -print0 | $_xargs -0 -I {} $_chmod $_dperm {}
fi

You can run this script as follows:
./script /var/www/html/
./script /usr/lib/cgi-bin/

🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallCentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNCentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
20 comments… add one
  • Thankful guy Sep 17, 2008 @ 7:21

    Thanks a lot for the tutorial. Now I can change the permission of a folder and its subfolders without affecting files inside. i.e.:

    $ find folder_name -type d -exec chmod 775 ‘{}’ \;

  • Info Gaptek May 26, 2009 @ 4:07

    I found this page by googling.
    Thanks for your help!

  • jay Jun 21, 2009 @ 11:31

    Thanks for this amazing commands…!

  • Kiwi Chris Aug 5, 2009 @ 23:52

    Hi this was excellent I used what you had here to change my permissions
    I changed it a little to work the way I wanted, which was to change all in the path to permissions I wanted, also works for ownership.

    Use this method for Chown:

    find . /home/admin/data/ -type d -exec chown admin.admin {} \;
    find . /home/admin/data/ -type f -exec chown admin.admin {} \;

    Public_html

    find . /home/admin/public_html/ -type d -exec chmod 755 {} \;
    find . /home/admin/public_html/ -type f -exec chmod 644 {} \;

  • Zilverdistel Dec 11, 2010 @ 11:31

    Thanks! I used it this way, after changing uid for a user:

    find -gid 1000 -exec chown -h :username {} \;

  • birkopf Aug 8, 2011 @ 11:30

    Excellent. Finally after weeks of searching this worked like a charm. Using the opportunity:
    – Is there a way to search (for example) all files with permission 700 and select all that are NOT 700 ? I mean inverse selection.

  • sha Sep 7, 2011 @ 16:14

    I thank you so much for highlighting this wonderful command.

  • Birkopf Sep 8, 2011 @ 10:03

    If you use gnome you can also do graphical way in nautilus. Do as follow:

    1) open gconf (for example in terminal or Alt+F2)
    2) in gconf-editor under /apps/nautilus/preferences select “show_advanced_permissions”
    3) close, open nautilus, right click on folder or file, select permissions and enjoy… :)

  • Poum Nov 28, 2011 @ 14:14

    Thank you, that’s cool.

  • Andy Jan 1, 2012 @ 4:59

    Do not do what I did. In a brief moment of aloofness, I happened to mistake “./” with “/.”

    The “./” means this directory while the latter “/.” means root… where all the apps are installed…

    :(

    • Çağrı May 11, 2012 @ 12:42

      Thnx man, that’s a good point : )

  • Outsourcing Nepal Jan 3, 2012 @ 8:38

    Still wondering warys to accomplish the task in cuteftp

  • vonbeau Mar 25, 2012 @ 5:46

    Great help, thank you.. I rsynced to server with -a [archive] switch and it changed the file permissions so smb didn’t work any longer… Anyway, thank you again.

  • viraj Mar 30, 2012 @ 22:05

    hi all.
    Having a great pleasure for the above posted answer,but i have got a doubt that
    how would we change the permission for some specific files having only read permission
    to both read and execute through shell script.

  • Francis Sep 18, 2012 @ 14:02

    Hey Vivek,

    I went trawling the web for an elegant and simple solution to this and decided to write a little script for this myself.

    It basically does the recursive chmod but also provides a bit of flexibility for command line options (sets directory and/or file permissions, or exclude both it automatically resets everything to 755-644). It also checks for a few error scenarios.

    Check it out:
    http://bigfloppydonkeydisk.blogspot.com.au/2012/09/recursively-chmod-only-files-or.html

    Hope it helps!

  • Hari Jun 14, 2013 @ 15:00

    Thank you. This really helped me

  • Engin Nov 3, 2013 @ 18:04

    Ty for article, really looking for permissions important.

  • auchomage Apr 6, 2014 @ 21:29

    This has saved me a lot time and trouble. Thank you for sharing this information.

  • ankush Apr 16, 2015 @ 14:59

    default system setting is 022,
    Is there a way we can change the umaskmode for individual users?

    Example:
    Any directory/file created by srv-test would have a umask of 002 results if dir/file permissions of rwxrwxr-x.

    any script or something that is use for this,
    user/dir/file have same permission i.e. 755.
    all the directory and file inside the user have same permission.755

  • Fritz Ulysse Feb 11, 2017 @ 0:35

    use the command _________________ to remove read, write, and execute permissions for other users from all files (ONLY FILES NOT DIRECTORIES)

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.