1. Overview

In Unix-based operating systems, access to files is restricted using the concept of access rights such as read, write, and execute.

In this tutorial, we’ll learn different ways to get file permissions in the octal format.

2. Using the stat Command

The stat command is the recommended strategy if we need to know the file permissions without any filters. In addition, it supports the –format option that accepts different format strings to get specific details about files, such as %a to get octal permission, %n to get the filename, and many others.

Let’s go ahead and get the octal file permissions for all the files under the*/bin* directory whose filename begins with the “w” character:

$ stat --format="%n: %a" /bin/w*
/bin/w: 755
/bin/wall: 2755
/bin/watch: 755
/bin/wc: 755
/bin/wdctl: 755
/bin/whatis: 755
/bin/whereis: 755
/bin/which: 777
/bin/which.debianutils: 755
/bin/who: 755
/bin/whoami: 755
/bin/write: 777
/bin/write.ul: 2755

We can notice that each line of the output contains a filename with its permissions in octal format. Moreover, we needed the %n format string to identify which permissions belong to which file.

Next, let’s get the file permissions for the /bin/whereis file by limiting the format string to “*%a*“:

$ stat --format="%a" /bin/whereis
755

Great! We’ve got this right. The output is limited to the octal permissions of the file, so we can use the result directly in a script if required.

3. Using the find Command

The find command in Linux is the standard way to search for file information. It offers advanced filter options such as -name, -type, -size, and so on to restrict the search results. Moreover, we can use the -printf option to get the file information in the desired format.

First, let’s go ahead and use the find command to get octal permission information for all files within the /bin directory, such that their name starts with the “w” character:

$ find /bin/ -name "w*" -printf "%f: %m\n"
whereis: 755
wc: 755
which.debianutils: 755
watch: 755
whoami: 755
wall: 2755
which: 777
who: 755
wdctl: 755
w: 755
write: 777
whatis: 755
write.ul: 2755

Great! The result looks correct. Furthermore, we must note that we used the %f and %m format strings to get the filename and octal permissions, respectively.

4. Using the ls and sed Commands

Yet another way to derive the octal permissions is by using the ls and sed commands.

First, let’s use the ls command with the -l option to see verbose file information:

$ ls -l /bin/w*
-rwxr-xr-x 1 root root 18440 Feb 25  2022 /bin/w
-rwxr-sr-x 1 root tty  18592 Feb 21  2022 /bin/wall
-rwxr-xr-x 1 root root 35192 Feb 25  2022 /bin/watch
-rwxr-xr-x 1 root root 35136 Feb  7  2022 /bin/wc
-rwxr-xr-x 1 root root 26808 Feb 21  2022 /bin/wdctl
-rwxr-xr-x 1 root root 39952 Mar 17  2022 /bin/whatis
-rwxr-xr-x 1 root root 27232 Feb 21  2022 /bin/whereis
lrwxrwxrwx 1 root root    23 Nov 30 02:16 /bin/which -> /etc/alternatives/which
-rwxr-xr-x 1 root root   946 Mar 23  2022 /bin/which.debianutils
-rwxr-xr-x 1 root root 39288 Feb  7  2022 /bin/who
-rwxr-xr-x 1 root root 22888 Feb  7  2022 /bin/whoami
lrwxrwxrwx 1 root root    23 Feb 28 04:34 /bin/write -> /etc/alternatives/write
-rwxr-sr-x 1 root tty  18600 Feb 21  2022 /bin/write.ul

We can see that the first column of the output contains the file permissions, but it’s not in the octal format. Further, we can use the sed command to replace the file permissions’ rwx- characters with their equivalent 0-7 octal representation to get the desired result.

Next, let’s pipe the output of the ls command to a series of sed substitution commands:

$ ls -l /bin/w* | \
sed -E -e 's/([^ ]*) .* (.*)/\1:\2/' \
-e 's/^[bcCdlps?]//' \
-e 's/rw[sx]/7/g' \
-e 's/rw-/6/g' \
-e 's/r-[sx]/5/g' \
-e 's/r--/4/g' \
-e 's/-w[sx]/3/g' \
-e 's/-w-/2/g' \
-e 's/--[sx]/1/g' \
-e 's/---/0/g' \
-e 's/^-//'
755:/bin/w
755:/bin/wall
755:/bin/watch
755:/bin/wc
755:/bin/wdctl
755:/bin/whatis
755:/bin/whereis
777:/etc/alternatives/which
755:/bin/which.debianutils
755:/bin/who
755:/bin/whoami
777:/etc/alternatives/write
755:/bin/write.ul

We must note that the first substitution command extracts the first and last column containing file permission and filename from the output of the ls command. Further, we ignored the first leading character among the [bcCdlps] characters as they represent the file type.

Finally, we should remember that this approach doesn’t handle special file permissions. Nonetheless, it’s good to know from a learning perspective.

5. Using the ls and awk Commands

awk offers common programming constructs such as if-else blocks. As a result, we can improve our computing logic to get the octal file permissions using awk instead of sed by handling the sticky bits.

Let’s write the script.awk script that takes input from the ls -l command and prints the octal file permissions along with the filename:

$ cat script.awk
{
    decimal_perm=0;
    for(i=0;i<=8;i++) {
        if (substr($1,i+2,1)~/[s]/) {
            decimal_perm += ((substr($1,i+2,1)~/[s]/)*2^9);
        } else {
            decimal_perm+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));
        }
    }

    if (k) {
        printf("%0o %s\n",decimal_perm, $NF);
    }
}

We can see that we’re computing the decimal value of the permission in the decimal_perm variable and eventually printing its octal representation. Further, we’re iterating over the characters of the permission string and matching it against [s] or [rwx] permissions. Accordingly, we increment decimal_perm with the equivalent decimal value for a sticky or regular bit with 2^9 or 2^(8-i), respectively.

Finally, let’s see the script in action:

$ ls -l bin/w* | awk -f script.awk
755 bin/w
1745 bin/wall
755 bin/watch
755 bin/wc
755 bin/wdctl
755 bin/whatis
755 bin/whereis
777 /etc/alternatives/which
755 bin/which.debianutils
755 bin/who
755 bin/whoami
777 /etc/alternatives/write
1745 bin/write.ul

6. Using the exa Command

exa is popularly known as a modern replacement for ls. Using exa, we can get the octal file permissions directly using the –octal-permissions option, so we don’t need any lengthy custom script.

Before we start, we need to install the exa package because it doesn’t come preinstalled:

$ apt-get install exa

Next, let’s go ahead and see it in action:

$ exa -l --octal-permissions bin/w*
0755 .rwxr-xr-x 18k root 25 Feb  2022 bin/w
2755 .rwxr-sr-x 19k root 21 Feb  2022 bin/wall
0755 .rwxr-xr-x 35k root 25 Feb  2022 bin/watch
0755 .rwxr-xr-x 35k root  7 Feb  2022 bin/wc
0755 .rwxr-xr-x 27k root 21 Feb  2022 bin/wdctl
0755 .rwxr-xr-x 40k root 17 Mar  2022 bin/whatis
0755 .rwxr-xr-x 27k root 21 Feb  2022 bin/whereis
0777 lrwxrwxrwx  23 root 30 Nov  2022 bin/which -> /etc/alternatives/which
0755 .rwxr-xr-x 946 root 23 Mar  2022 bin/which.debianutils
0755 .rwxr-xr-x 39k root  7 Feb  2022 bin/who
0755 .rwxr-xr-x 23k root  7 Feb  2022 bin/whoami
0777 lrwxrwxrwx  23 root 28 Feb 04:34 bin/write -> /etc/alternatives/write
2755 .rwxr-sr-x 19k root 21 Feb  2022 bin/write.ul

We can see that the first column represents the octal permission. Further, if required, we can limit the output to octal permissions and filename using utilities such as awk, sed, or cut commands.

7. Conclusion

In this article, we learned how to get the octal permissions of files in Linux. Further, we explored multiple options with the stat, find, sed, awk, and exa commands to solve the use case.