1. Overview
Sometimes, we may have to change the file permissions in a directory recursively. For example, the file permissions may not have been preserved during copying. One reason might be the default file permissions of the current user. If the file permissions aren’t retained, we may have to revert the file permissions of the copied files.
In this tutorial, we’ll discuss how to fix the file permissions in a directory recursively.
2. Example Setup
Let’s create several directories and files to analyze the problem:
$ pwd
/tmp
$ mkdir directory1
$ mkdir directory1/directory11
$ mkdir directory1/directory12
$ touch directory1/file1
$ touch directory1/directory11/file111
$ touch directory1/directory11/file112
$ touch directory1/directory12/file121
$ touch directory1/directory12/file122
Now, let’s check the contents of directory1 with the ls command:
$ ls –Rl directory1
directory1:
total 8
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory11
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory12
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file1
directory1/directory11:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file111
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file112
directory1/directory12:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file121
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file122
The -R option of ls allows us list the subdirectories recursively. The -l option uses a long listing format.
As we see, the directories created have the permission 755. The files, on the other hand, have the permission 644.
Now, let’s change the permissions of the directories and files in directory1 to 777 recursively using the -R option of chmod:
$ chmod –R 777 directory1/*
$ ls –Rl directory1
directory1:
total 8
drwxrwxrwx 2 alice alice 4096 Nov 8 07:56 directory11
drwxrwxrwx 2 alice alice 4096 Nov 8 07:56 directory12
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file1
directory1/directory11:
total 0
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file111
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file112
directory1/directory12:
total 0
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file121
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file122
The result of the ls -Rl command after changing the permissions shows that we successfully changed the permissions.
Our goal is to revert the permissions of the subdirectories to 755 and the permissions of the files to 644 in directory1.
3. Using the exec Option of find
The find command is useful for searching files in a directory hierarchy. We can also specify a command to run with the matched files using its -exec option. We’ll use chmod for the matched files to correct the permissions.
3.1. Fixing the Directory Permissions
First, we’ll fix the directory permissions:
$ pwd
/tmp
$ find directory1/* –type d –exec chmod 755 {} +
The -type option of find specifies the type of the searched files. -type d means that we want to search for directories. Therefore, the find directory/* -type d part of the last command specifies that we want to find the directories in the directory directory1.
The -exec chmod 755 {} + part of the command, on the other hand, specifies to apply the chmod 755 command to the found subdirectories. Because of the + in the command, chmod was applied once to all of the found directories, i.e., we applied the command chmod 755 directory1/directory11 directory1/directory12.
We could also use \; instead of +. In that case, find would apply the chmod command separately for each found subdirectory.
Now, let’s check the contents of directory1:
$ ls –Rl directory1
directory1:
total 8
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory11
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory12
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file1
directory1/directory11:
total 0
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file111
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file112
directory1/directory12:
total 0
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file121
-rwxrwxrwx 1 alice alice 0 Nov 8 07:56 file122
The output of ls shows that we were successful in reverting the permissions of the directories.
3.2. Fixing the File Permissions
Now, let’s correct the permissions of the files in directory1:
$ find directory1/* –type f –exec chmod 644 {} +
$ ls –Rl directory1
directory1:
total 8
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory11
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory12
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file1
directory1/directory11:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file111
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file112
directory1/directory12:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file121
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file122
We used -type f this time for finding only the regular files. The output of ls shows that we were also successful in correcting the permissions of the files.
4. Using find With Command Substitution
A slightly modified combination of find and chmod can be used to correct the permissions.
4.1. Fixing the Directory Permissions
We’ll use the following command to fix the directory permissions:
$ chmod 755 $(find directory1/* -type d)
Here, we first find the directories in directory1 using find. Then we pass the found directories to chmod using command substitution.
4.2. Fixing the File Permissions
Similarly, we can use the following command to change the permissions of the files:
$ chmod 644 $(find directory1/* -type f)
Here, we first find the files in directory1 using find. Then we pass the found files to chmod again using command substitution.
5. Using find and xargs
Another alternative is to combine find and xargs using a pipe for correcting the file permissions.
5.1. Fixing the Directory Permissions
Let’s start with fixing the directory permissions:
$ pwd
/tmp
$ find directory1/* -type d –print0 | xargs -0 chmod 755
First, we look for the directories in directory1 with an additional parameter -print0. This option of find prints the found files or directories with a null character between them.
For clarity, let’s run only the first part of the command before the pipe:
$ find directory1/* -type d –print0
/directory1/directory12directory1/directory11
The output displays the two subdirectories, namely directory1/directory12 and directory1/directory11. They seem to be appended because of the null character between them.
We use the xargs command in the second part. xargs converts the input from the standard input to arguments for a command. Its -0 option specifies that the input items are separated by a null character. We can also use the –null option instead.
We must use the -0 option in our case because of the -print0 option we used with find. Therefore, xargs passes each directory found by find to chmod as parameters.
5.2. Fixing the File Permissions
Let’s apply the same command for files, and list the permissions:
$ find directory1/* -type f –print0 | xargs -0 chmod 644
$ ls –Rl directory1
directory1:
total 8
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory11
drwxr-xr-x 2 alice alice 4096 Nov 8 07:56 directory12
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file1
directory1/directory11:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file111
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file112
directory1/directory12:
total 0
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file121
-rw-r--r-- 1 alice alice 0 Nov 8 07:56 file122
As we can see from the output, we successfully reverted the permissions.
6. Conclusion
In this article, we discussed how to fix the file permissions in a directory recursively.
Firstly, we used find together with its -exec option. We applied the chmod command to the found files or directories using the -exec option.
Secondly, we applied a slightly modified version of the first method. We used command substitution to pass the files or directories found by find to chmod.
Finally, we used the -print0 option of find and passed the found files or directories to xargs. xargs used chmod to change the permissions.