Home » Questions » Computers [ Ask a new question ]

How to recursively chmod all directories except files?

How to recursively chmod all directories except files?

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

Asked by: Guest | Views: 384
Total answers/comments: 5
bert [Entry]

"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"
bert [Entry]

"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."
bert [Entry]

"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."
"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."
bert [Entry]

"I post my solution because I don't see an almost-every cases solution using only chmod:

Only chmod : smooth permissions on files and dirs

For my example I created multiple files with different permissions:

> tree -p chmodtests/
chmodtests/
├── [drwxr-xr-x] aa/
│   ├── [drwxr-xr-x] a1/
│   │   ├── [-r--r--r--] read_only
│   │   ├── [-rw-rw-rw-] read_w
│   │   └── [-rwxrwxrwx] read_wx*
│   ├── [drwxr-xr-x] a2/
│   ├── [-r--------] read_only
│   ├── [-rw-------] read_w
│   └── [-rwx------] read_wx*
└── [drwxr-xr-x] bb/

4 directories, 6 files

then apply this command:

chmod -vR a=r-wx,u=wr,a+X chmodtests/

output:

mode of 'chmodtests/' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/a1' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/a1/read_only' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a1/read_w' changed from 0666 (rw-rw-rw-) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a1/read_wx' changed from 0777 (rwxrwxrwx) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/read_only' changed from 0400 (r--------) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a2' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/read_w' changed from 0600 (rw-------) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/read_wx' changed from 0700 (rwx------) to 0644 (rw-r--r--)
mode of 'chmodtests/bb' retained as 0755 (rwxr-xr-x)

result: all files are 644; all dirs are 755

> tree -p chmodtests/
chmodtests/
├── [drwxr-xr-x] aa/
│   ├── [drwxr-xr-x] a1/
│   │   ├── [-rw-r--r--] read_only
│   │   ├── [-rw-r--r--] read_w
│   │   └── [-rw-r--r--] read_wx
│   ├── [drwxr-xr-x] a2/
│   ├── [-rw-r--r--] read_only
│   ├── [-rw-r--r--] read_w
│   └── [-rw-r--r--] read_wx
└── [drwxr-xr-x] bb/

Explanation part

tl;dr explanation:

this command removes all execution/search on files and directories and then add execution/search only for dirs

chmod -vR : verbose and recursive

a=r-wx:

a: meaning all (user, group and other)
=: set permissions to (do not add nor remove)
r-wx: read only permissions

u=wr: user can read and write

a+X: add execution/search only for directories (for all types u,g,o)

Other example

Now let's say I only want 600 for files and 700 for dirs:

chmod -vR a=-rwx,u=rw,u+X chmodtests/

Limits

With this method you cannot set r and w differently for file and dirs.

E.g. you cannot have the following

drwxr-xr-x dir/
-r-------- dir/myfile

hth"
bert [Entry]

"You can also use tree:

tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 ""$1""' -- '{}'

and if you want to also view the folder add an echo

tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 ""$1"" && echo$1' -- '{}'"