Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How to chmod 755 all directories but no file (recursively) ?

Inversely, how to chmod only files (recursively) but no directory ?

share|improve this question

6 Answers 6

up vote 207 down vote accepted

To recursively give directories read&execute privileges:

find /path/to/base/dir -type d -exec chmod 755 {} +

To recursively give files read privileges:

find /path/to/base/dir -type f -exec chmod 644 {} +

Or, if there are many objects to process:

chmod 755 $(find /path/to/base/dir -type d)
chmod 644 $(find /path/to/base/dir -type f)

Or, to reduce chmod spawning:

find /path/to/base/dir -type d -print0 | xargs -0 chmod 755 
find /path/to/base/dir -type f -print0 | xargs -0 chmod 644
share|improve this answer
19  
If there are “lots” of directories/files, it might be worth it to use xargs to avoid spawning one chmod process per entry: find /path/to/base/dir -type d -print0 | xargs -0 chmod 755. –  Chris Johnsen Jan 6 '10 at 6:06
14  
its better to change 755 to 644 in your Files example, some guys may copy/paste it! –  Mohammad Ali Akbari Aug 8 '12 at 7:07
5  
"find" usually allows a "+" instead of "\;", and will then run as few exec:s as possible. Makes a BIG difference when there are lots of files, and cleaner than the proposed "xargs" solution. –  Pontus Dec 20 '12 at 21:59
3  
To bring @Pontus comment full circle, the command to run chmods efficiently using find only is (for directories): find /path/to/dir -type d -exec chmod 755 {} + (for files): find /path/to/dir -type f -exec chmod 644 {} + –  trisweb Feb 4 '13 at 15:34
1  
@juanpastas look at the man page for find; search for a description of -exec command {} +. More at this SO answer . –  nik Sep 14 '13 at 17:53

A common reason for this sort of thing is to set directories to 755 but files to 644. In this case there's a slightly quicker way than nik's find example:

chmod -R u+rwX,go+rX,go-w /path
share|improve this answer
1  
o_O Would you be able to dissect that command for us? Thanks! –  Babu Jan 6 '10 at 4:46
2  
-R = recursively; u+rwX = Users can read, write and execute; go+rX = group and others can read and execute; go-w = group and others can't write –  släcker Jan 6 '10 at 7:08
32  
The important thing to note here is that X acts differently to x - the man page says The execute/search bits if the file is a directory or any of the execute/search bits are set in the original (unmodified) mode. In other words, chmod u+X on a file won't set the execute bit; and g+X will only set it if it's already set for the user. –  James Polley Jan 6 '10 at 9:34
4  
The upper case X is the key here guys... –  d-_-b Jun 6 '11 at 16:46
3  
This pattern won't fix the situation when someone has done chmod -R 777 since the +X option will not reset existing execute bits on files. Using -x will reset directories, and prevent descending into them. –  Andrew Vit Aug 7 '12 at 4:57

If you want to make sure the files are set to 644 and there are files in the path which have the execute flag, you will have to remove the execute flag first. +X doesn't remove the execute flag from files who already have it.

Example:

chmod -R ugo-x,u+rwX,go+rX,go-w path

Update: this appears to fail because the first change (ugo-x) makes the directory unexecutable, so all the files underneath it are not changed.

share|improve this answer
    
This works for me, and I don’t see why it wouldn’t. (Sure, if you did just chmod -R ugo-x path, that might be a problem. But the complete command will do the chmod u+rwX on each directory before it tries to descend into it.) However, I believe that chmod R u=rw,go=r,a+X path is sufficient – and it’s shorter. –  Scott Jul 8 at 0:25

I decided to write a little script for this myself.

Recursive chmod script for dirs and/or files — Gist

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.

I also wrote about it on my blog.

share|improve this answer

Try this python script; it requires no spawning of processes and does only two syscalls per file. Apart from an implementation in C, it will probably be the fastest way of doing it (I needed it to fix a filesystem of 15 million files which were all set to 777)

#!/usr/bin/python3
import os
for par, dirs, files in os.walk('.'):
    for d in dirs:
        os.chmod(par + '/' + d, 0o755)
    for f in files:
        os.chmod(par + '/' + f, 0o644)

In my case, a try/catch was required around the last chmod, since chmodding some special files failed.

share|improve this answer

You could use the following bash script as an example. Be sure to give it executable permissions (755). Simply use ./autochmod.sh for the current directory, or ./autochmod.sh <dir> to specify a different one.

#!/bin/bash

if [ -e $1 ]; then
    if [ -d $1 ];then
        dir=$1
    else
        echo "No such directory: $1"
        exit
    fi
else
    dir="./"
fi

for f in $(ls -l $dir | awk '{print $8}'); do
    if [ -d $f ];then
        chmod 755 $f
    else
        chmod 644 $f
    fi
done
share|improve this answer
    
This is incredibly long. this is much simpler. –  kapad Jul 19 '13 at 9:29
    
Wow! So many problems! (1) If $1 is not null, but is not the name of a directory (e.g., is a typo), then dir gets set to . with no message. (2) $1 should be "$1" and $dir should be "$dir". (3) You don’t need to say "./"; "." is fine (and, strictly speaking, you don’t need quotes here). (4) This is not a recursive solution. (5) On my system, ls -l … | awk '{ print $8 }' gets the files’ modification times. You need { print $9 } to get the first word of the filename. And even then, (6) this does not handle filenames with white space. … –  Scott Jul 7 at 22:59
    
… And, last but not least (∞) if this script is in the current directory, it will chmod itself to 644, thus making itself non-executable! –  Scott Jul 7 at 23:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.