How to apply chmod recursively with best practices & examples

Let me guess if you are here, not able to assign permission to directories and files? Getting permission denied error? Or you have a lot of directories and files and trying to figure how how to use chmod recursively to change permissions? Do you want to apply 777 or 755 permission across all the files or directories?

Well you are at the right place. In this tutorial guide I will help us understand the usage of chmod and how you can change permissions of files and directories using a single command

 

What is chmod?

  • chmod is a GNU utility which is provided as part of coreutils rpm in Linux distributions
  • chmod is short abbreviation for "Change Mode"
  • It is used to change the file mode bits of each given file/directory according to mode.
  • You can either use symbolic representation of changes or an octal number representing the bit pattern for the new mode bits.
  • The format of a symbolic mode is [ugoa...][[-+=][perms...]...] where perms is either zero or more letters from the set rwxXst
  • You can also add/modify/remove special permissions such as setuid, setgid, sticky bit with chmod

 

What is --preserve-root? Why you should use it?

  • In this tutorial I will be using --preserve-root with all of my chmod commands
  • This is a recommended option to use when you are planning to assign permission recursively as this can be destructive
  • Imagine by mistake you removed all permission from / (root) directory, this would lead in an unusable system
  • It is similar to running rm -rf / which if you are a Linux Administrator should know, this can destroy your server
  • With --preserve-root we inform the command not to modify root directory permission

DO NOT USE THIS COMMAND

# chmod --changes --recursive 755 /

Snippet from my terminal with this command, see the damage this command can do to your server.

chmod recursive usage guide for absolute beginners
chmod recursive

This would recursively change the permission of all files and dir under / which can also destroy your system

In such case it is always recommended to use

# chmod --changes --recursive --preserve-root 755 /
chmod: it is dangerous to operate recursively on '/'
chmod: use --no-preserve-root to override this failsafe

It may not be possible to use this additional option every time with chmod so you can create an alias

# alias chmod='chmod --preserve-root'

and also add this to your /etc/bashrc or individual user's .bashrc file for permanent changes

Now if we use chmod, it does not allow to modify root permission

# chmod -c --recursive 755 /
chmod: it is dangerous to operate recursively on '/'
chmod: use --no-preserve-root to override this failsafe

 

Linux Permissions Syntax

You can use this table to understand the different symbolic or octal value to use with chmod

PermissionOctalSyntax (Symbolic)
read+write+execute4+2+1=7rwx
read+write4+2+0=6rw-
read+execute4+0+1=5r-x
read4+0+0=4r--
write+execute0+2+1=3-wx
write0+2+0=2-w-
execute0+0+1=1--x

 

Perform chmod recursive with -R or --recursive

If all your files and directories are under one parent directory then you can directly use chmod -R <dir_name> to assign the permission recursively

The syntax to modify the file and directory permission recursively:

chmod [--changes|-c] {--recursive|-R} {PATH}

I hope you know, in a syntax anything under square braces [] is optional and anything under curly braces {} is mandatory

In this syntax I have also added --changes or -c as optional as this will inform you if the change really happened in the backend

To assign 755 permission of all files and directories under /opt/dir

# chmod -c -R 755 /opt/dir

This would also remove any special permission if already assigned to any of the files or directories under /opt/dir. For example, I created a file with Sticky Bit Special permission under /opt/dir. Once I apply chmod recursively, the special sticky bit permission was also removed

mode of '/opt/dir/' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/opt/dir/file' changed from 7555 (r-sr-sr-t) to 0750 (rwxr-x---)
IMPORTANT NOTE:

If you want to change permission of files and directories under /opt/dir and not the permission of /opt/dir itself then you should use chmod -c -R <permission> /opt/dir/*. This will change permission of everything under /opt/dir/ but not for dir directory itself

You can also use octal method here, in this example I have added full permission to user, read and execute permission for for group and removed all permission from others which is equivalent to 750 in octal method

# chmod -c -R u+rwx,g+rx,o-rwx /tmp/dir1/*
mode of '/tmp/dir1/dir2/file5' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3/file1' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3/file2' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3/file5' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3/file3' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)
mode of '/tmp/dir1/dir2/dir3/file4' changed from 0755 (rwxr-xr-x) to 0750 (rwxr-x---)

Verify the permission

# tree -p /tmp/dir1/
/tmp/dir1/
├── [drwxr-x---]  dir2
│   ├── [drwxr-x---]  dir3
│   │   ├── [-rwxr-x---]  file1
│   │   ├── [-rwxr-x---]  file2
│   │   ├── [-rwxr-x---]  file3
│   │   ├── [-rwxr-x---]  file4
│   │   └── [-rwxr-x---]  file5
│   └── [-rwxr-x---]  file5
└── [-rwxr-x---]  file10

2 directories, 7 files

Since I used /tmp/dir1/* in my command, the permission of dir1 is not modified.

# ls -ld /tmp/dir1/
drwxr-xr-x 3 root root 4096 May 23 12:02 /tmp/dir1/
WARNING:

Make sure you check the command properly before executing chmod recursively as it is ir-reversible

Now some of the drawbacks of above command

  1. It will modify the permission of all the files and directories under single path. If you have many files or directory under different locations such as /opt, /var, /tmp then you will end up executing chmod multiple times
  2. There is no way to differentiate between files and directories. If you have a requirement to change permission of only files or directories then the tool itself can not handle this
  3. Similarly if you want to change permission of certain files or directory with specific naming syntax, the tool can not handle itself such filter

So we need find command to take care of these filters before applying chmod command

find can apply these filters and then it can be combined with exec or xargs to execute chmod command. If you use find in combination with chmod then you do not need --recursive or -R as find itself will search all the files and pass individual file for chmod as an input argument. Let me give you some examples to help you understand better:

 

Use find with exec to change permission

I have already written a descriptive tutorial to learn and understand find and exec combination.
The syntax to change permission using find with chmod would be

find {PATH} [OPTIONS] -exec [COMMAND] {} \;
  • Replace PATH with the location of your files or directories
  • You can choose all the supported options with find command such as define -type, or -name etc
  • Replace COMMAND with chmod <permission>
  • Do not remove or replace {} \; as this will be used by find to recursively look for files or directories and provide the found file as an input argument to COMMAND
  • So if find command finds a file named myfile then the COMMAND would become "chmod <permission> myfile"

Search for all files under /tmp and change their permission to 644

# find /tmp -type f -exec chmod --changes 644 {} \;

To assign the same permission using symbolic method:

# find /tmp -type f -exec chmod --changes u=rw,go=r {} \;

Search for all directories under /tmp and change their permission to 755

# find /tmp -type d -exec chmod --changes 755 {} \;

To assign the same permission using symbolic method:

# find /tmp -type d -exec chmod --changes u=rwx,go=rx {} \;

 

Use find with xargs to change permission

Similarly you can also combine find with xargs to assign permission recursively

The syntax to use find with xargs and chmod would be:

find {PATH} [OPTIONS] -print0 | xargs -0 [COMMAND]

Here,
-print0 Tells find to print all results to std, each separated with the ASCII NUL character ‘\000’
-0 Tells xargs that the input will be separated with the ASCII NUL character ‘\000’

Search for all files under /tmp and change their permission to 644

# find /tmp -type f -print0 | xargs -0 chmod --changes 644

To assign the same permission using symbolic method:

# find /tmp -type f -print0 | xargs -0 chmod --changes u=rw,go=r

Search for all directories under /tmp and change their permission to 755

find /tmp -type d -print0 | xargs -0 chmod --changes 755

To assign the same permission using symbolic method:

# find /tmp -type d -print0 | xargs -0 chmod --changes u=rw,go=rx

 

Conclusion

chmod can be used with -R or also referred as --resursive to assign/modify permission to files and directories recursively. Although it is recommended to use --changes and --preserve-root along with the command to avoid any destruction.
It is possible that you may not want out STDOUT on the screen so you can choose to reduce all messages and errors to a different file by using

# chmod --recursive --changes 755 /tmp/dir1/ >& /tmp/logfile

So this would store all the output to /tmp/logfile which you can use for debug purpose.

Lastly I hope the steps from the article to apply chmod recursively on Linux was helpful. So, let me know your suggestions and feedback using the comment section.

 

References

I have used below external references for this tutorial guide
man page for chmod

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.