1. Introduction
Permissions are one of the most important mechanisms to secure and regulate access to filesystem objects. So, being aware of the current permission set for a file, directory, or directory hierarchy can be critical. This is especially true for use cases like web, application, and database servers, as well as similar external-facing services.
In this tutorial, we explore ways to view the permissions of all filesystem objects under or along a given path. First, we look at a classic tool for listing metadata. Next, we try to improve the readability with another common utility for directory hierarchies. After that, we turn to path tracing with permission listing. Finally, we mimic a more complex command via a Bash script and a basic toolset.
Importantly, none of the methods we discuss output the ACL (Access Control List) and SELinux MAC (Mandatory Access Control) configuration.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.
2. Using ls
Naturally, we start with the ubiquitous ls command, which can list the permissions of every object in and under a given path:
$ ls --recursive -l ./dir/
./dir/:
total 8
drwxr-xr-x 4 baeldung baeldung 4096 Jun 6 06:56 subdir1
drwxr-xr-x 2 baeldung baeldung 4096 Jul 7 07:07 subdir2
./dir/subdir1:
total 12
-rw-r--r-- 1 baeldung baeldung 666 Jun 21 06:21 filea
dr--r--r-- 2 baeldung baeldung 4096 Jun 26 06:26 subdir11
dr--r-xr-- 2 baeldung baeldung 4096 Jun 22 22:22 subdir12
./dir/subdir1/subdir11:
total 0
./dir/subdir1/subdir12:
total 4
-r-------x 1 baeldung baeldung 9 Jun 30 06:30 fileaa
./dir/subdir2:
total 8
-rw-r--r-- 1 baeldung baeldung 3 Jun 6 06:23 fileb
-rw-r--r-- 1 baeldung baeldung 4 Jun 6 06:23 filec
In this case, *we perform a –recursive (-R) [-l]ong listing of the ./dir/ directory*.
This way, we see the permissions for each filesystem object under ./dir/. However, the output might not be very convenient or human-readable.
3. Using tree
Perhaps the main function of the tree command is to provide an easier-to-comprehend view of a directory structure when compared to more standard tools like ls.
Let’s see the typical output of tree:
$ tree ./dir/
./dir/
├── subdir1
│ ├── filea
│ ├── subdir11
│ └── subdir12
│ └── fileaa
└── subdir2
├── fileb
└── filec
4 directories, 4 files
Generally, the indented output of the tree command is easier to follow.
Now, let’s see how we can also add some metadata for each object next to it:
$ tree -pu ./dir/
./dir/
├── [drwxr-xr-x baeldung] subdir1
│ ├── [-rw-r--r-- baeldung] filea
│ ├── [dr--r--r-- baeldung] subdir11
│ └── [dr--r-xr-- baeldung] subdir12
│ └── [-r-------x baeldung] fileaa
└── [drwxr-xr-x baeldung] subdir2
├── [-rw-r--r-- baeldung] fileb
└── [-rw-r--r-- baeldung] filec
4 directories, 4 files
*By adding the -p and -u flags to tree, we include the [-p]ermissions and owning [-u]ser to the output of each file and directory in the hierarchy*.
4. Using namei
When we only need the permissions of each element along a path, we can use the namei command:
$ namei -mo ./dir/subdir1/subdir12/fileaa
f: ./dir/subdir1/subdir12/fileaa
drwx------ baeldung baeldung .
drwxr-xr-x baeldung baeldung dir
drwxr-xr-x baeldung baeldung subdir1
dr--r-xr-- baeldung baeldung subdir12
-r-------x baeldung baeldung fileaa
This way, we don’t get metadata about all filesystem objects under a given directory, but we return the permission [-m]odes and [-o]wner for every part of a path.
5. Using Bash Script to Mimic namei
As usual, we can achieve our goal of showing the permissions of all filesystem objects along a given path via a Bash script. Of course, we leverage some of the options above in combination with some additional tools.
In particular, we can employ the common readlink, ls, and dirname commands to get the behavior of namei:
$ cat namei.sh
#!/usr/bin/env bash
ppath="$(readlink -f "$1")"
while [ "$ppath" != / -a "$ppath" != . ]; do
ls -ld "$ppath"
ppath="$(dirname -- "$ppath")"
done
$ chmod +x namei.sh
After the usual shebang, the above namei.sh script uses readlink to get the full path to its first argument in the $ppath variable. Next, it uses a while loop that runs until $ppath is either / root or the . (period) current directory. On each iteration, ls lists $ppath and its metadata, ensuring that [-d]irectory objects are shown instead of their contents. After that, $ppath gets the value of its upper-level directory path via dirname within a subshell.
After making the script executable via chmod, let’s run it to see the result:
$ ./namei.sh ./dir/subdir1/subdir12/fileaa
-r-------x 1 baeldung baeldung 9 Jun 30 06:30 /root/dir/subdir1/subdir12/fileaa
dr--r-xr-- 2 baeldung baeldung 4096 Jun 22 22:22 /root/dir/subdir1/subdir12
drwxr-xr-x 4 baeldung baeldung 4096 Jun 6 06:56 /root/dir/subdir1
drwxr-xr-x 4 baeldung baeldung 4096 Jul 21 11:39 /root/dir
drwx------ 17 root root 2120666 Jul 23 00:23 /root
Unlike the output of namei, the listing from our script starts with the most specific and ends with the top-level object. To reverse that, we can pipe the while loop through sed:
$ cat namei.sh
#!/usr/bin/env bash
ppath="$(readlink -f "$1")"
while [ "$ppath" != / -a "$ppath" != . ]; do
ls -ld "$ppath"
ppath="$(dirname -- "$ppath")"
done | sed '1!G;h;$!d'
Here, we append a newline and add the hold space to the pattern space (G) for all but the 1! first line. After that, for all lines, we perform a [h]old to get the pattern space into the hold space. Finally, we [d]elete all but the $! last line. Effectively, this sequence reverses the line order. If available, we can also use tac for the same purpose.
6. Summary
In this article, we discussed ways to get the permissions of filesystem objects under or along a given path.
In conclusion, although there are tools, some more convenient than others, we can also achieve our aims with a Bash script and a basic toolset.