Linux Directory Permissions
Read, write and execute permissions are used for directories as well as files on Linux but their meaning for directories is not as straight forward1.
The permissions needed for each action are:
Action
|
Required Permission(s)
|
Listing the entries of the directory
|
Read
|
Adding or removing entries from the directory
|
Write and Execute (see also "Restricted Deletion" below)
|
"cd" into the directory
|
Execute
|
Accessing the directory entries' contents or entry metadata
|
Execute
|
Modifying the directory entries' contents or entry metadata
|
Execute
|
Remove the directory.
|
As with normal files, the permissions of the parent directory and not the directory itself determine if you can remove it. The directory must be empty.
|
Or listed inversely each permission allows:
Permission
|
Symbol
|
Value
|
Description for directories
|
Read
|
r
|
4
|
Allows listing the names of entries in the directory (e.g. using "ls") but not entry metadata or contents.
|
Write
|
w
|
2
|
Allows adding, removing or moving entries (but not their contents).
|
Execute
|
x
|
1
|
Allows accessing and modifying the entry contents and metadata. Also needed to add, delete or remove entries. Also called "Search" for directories2.
|
Playground
See how the following commands are handled when executed on a directory named testdir
that starts with a single file named A.txt
when the executing user has the permissions you choose:
$ chmod u= testdir
$ stat testdir
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0000/d---------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0100/d--x------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0200/d-w-------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0300/d-wx------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0400/dr--------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0500/dr-x------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0600/drw-------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
File: testdir
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 254,0 Inode: 57417470 Links: 2
Access: (0700/drwx------) Uid: ( 1000/ ben) Gid: ( 1000/ ben)
Access: 2030-01-01 08:30:00.000000000 -0000
Modify: 2030-01-01 08:30:00.000000000 -0000
Change: 2030-01-01 08:30:00.000000000 -0000
Birth: 2030-01-01 08:30:00.000000000 -0000
$ ls -l testdir
ls: cannot access 'testdir/A.txt': Permission denied
total 0
-????????? ? ? ? ? ? A.txt
ls: cannot open directory 'testdir': Permission denied
total 4
-rw-r--r-- 1 ben ben 12 Oct 12 2022 A.txt
$ cat testdir/A.txt
Lorem Ipsum
cat: testdir/A.txt: Permission denied
$ echo "New file" > testdir/B.txt
bash: line 1: testdir/B.txt: Permission denied
$ cd testdir
bash: line 1: cd: testdir: Permission denied
Examples explained
- A directory where your user has execute but not read permissions would allow you to edit or modify files that you can not list with "ls" if you already know their path.
- A directory where your user has write and execute but not read would allow you to add new files and modify existing files but not see them.
- A directory with only write permissions is the same as a directory with no permissions3.
- Most of the time you will always want to set execute if you are also setting either read or write.
More advanced permissions
- Restricted Deletion (also called Sticky Bit) - For directories only lets the file or directory owner move or delete a file inside the directory.
- Set Group Identity (setgid) - For directories causes new files to be created with the same group as the directory rather than the group of the process creating the file.
- Set User Identity (setuid) - Ignored by Linux and most Unix systems.
1. This article is focused on directory permissions. For an intro to Linux permissions in general you can read this Linux Foundation article, this article, the chmod man page or search for more.
2. The chmod man page is the main source of this page's information.
3. See this SO question. I like the OPs analogy of "execute" permitting access to inodes.
Written by Ben Hansen on 2022-10-04.
Feedback and
edit suggestions are appreciated.