chmod recursively on directories or files using find
by Mark on May.06, 2009, under sysadmin
Sometimes its the little things that annoy us so much on the Unix command line. One big question for me was… How to do you differentiate between directories and files when recursively chmod-ing?
The answer is simple. But of course there are different ways to do the same thing.
Using the find command
find -name '*' -type d -exec chmod 0755 {} \;
NOTE: the -name ‘*’ parameter is used to keep from modifying the present working directory or ‘.’ directory.
find . -type f -exec chmod 0644 {} \;
Using chmod with capital X
The capital X will cause directories and files that are executable (for user and group) to be set as executable. Other files will not be set as executable.
chmod -R ug+rX .
Other uses of the find command
Modifying specific file types:
find -name '*.pdf' -exec chmod 0755 {} \;
NOTE: you can insert any command in after the -exec but before the {} (chmod 0775) such as ‘chown’.
My common usage
I often setup new Wordpress installations. I like to get ownership and permission sorted out quickly. I’ll use this as my example.
In your Wordpress root directory:
chown your-username.www-data * -R
find -name '*' -type d -exec chmod 2750 {} \;
find . -type f -exec chmod 2640 {} \;
NOTE: the 2750 and 2640 sets a bit so that all directories that are created by the www-data user in my case will have the same permissions and ownership as the the other files. Otherwise the www-data user may create files that are owned by itself and the your-username may not be able to modify them easily.
Now change so that the wp-content/{uploads,plugins,themes} directories are writable to the www-data group. This is so that the web server can upload photos and auto-update plugins/themes.
cd wp-content
mkdir uploads
chown your-username.www-data uploads
find -name '*' -type d -exec chmod 2770 {} \;
find . -type f -exec chmod 2660 {} \;
November 5th, 2009 on 4:20 pm
Thanks so much for this information.
I just spent an hour trying to get chmod to work recursively inside of a for loop, but it kept barfing on filenames that contained spaces.
for foo in $(find /home2 -name “*”); do chmod 744 “$foo”; done
Your find/exec command with the curly braces fixed me right up.