ZetCode

Linux File Permissions

last modified October 23, 2026

Linux file permissions control who can read, modify, and execute files and directories. They are a basic security mechanism of every Unix-like system. This tutorial explains how permissions are represented and shows how to view and change them with ls, chmod, chown, chgrp, and umask.

Every file has an owner and a group. Permissions are defined separately for three classes of users: the owner, the group, and others. Each class can have three types of permissions: read, write, and execute. The root user bypasses these checks.

Basic permission types

The following table outlines the three fundamental permission types in Linux: read, write, and execute. Each permission has a specific symbol and an associated octal value, which are essential for configuring file and directory access.

Basic Permission Types
Permission Symbol Octal Value Description File Example Directory Example
Read r 4 Allows viewing file contents Reading a text file Listing directory contents (ls/dir)
Write w 2 Allows modifying contents Editing a file Creating/deleting files in directory
Execute x 1 Allows execution Running scripts/programs Accessing directory (cd)

These basic permissions form the foundation of Linux access control. For files, 'read' allows viewing contents, 'write' enables editing, and 'execute' permits running the file as a program or script.

For directories, the meanings shift slightly: 'read' lets you list contents, 'write' allows modifications like adding or removing files, and 'execute' is required to enter the directory with commands like cd.

The octal values (4, 2, 1) are used in numeric notation to combine permissions, as we'll see later.

User classes

This table introduces the three user classes that Linux permissions apply to: owner, group, and others. Each class is assigned specific permissions to control access levels.

User Classes
Class Symbol Description Typical Use Case
Owner/User u The file's creator or assigned owner Personal files with full control
Group g Users in the file's assigned group Team-shared files
Others o All other system users Public access files

In Linux, permissions are assigned separately to these three classes. The 'owner' is typically the user who created the file and often has the most privileges.

The 'group' consists of users assigned to a specific group (viewable with ls -l), useful for collaborative work.

'Others' encompasses everyone else on the system, often given minimal access for security. These distinctions allow fine-grained control, such as giving a team (group) read access while restricting outsiders (others).

Permission notation

The table below demonstrates how permissions are represented in both symbolic and octal notation, with examples showing common configurations and their breakdowns.

Permission Notation Examples
Type Example Octal Breakdown
Symbolic -rwxr-xr-x 755 Owner: rwx (7 = 4+2+1)
Group: r-x (5 = 4+1)
Others: r-x (5 = 4+1)
Symbolic -rw-r--r-- 644 Owner: rw- (6 = 4+2)
Group: r-- (4)
Others: r-- (4)
Symbolic -rwxrwxrwx 777 Owner: rwx (7 = 4+2+1)
Group: rwx (7 = 4+2+1)
Others: rwx (7 = 4+2+1)

Permission notation can be symbolic (e.g., rwxr-xr-x) or numeric (e.g., 755). The symbolic form uses 'r', 'w', and 'x' for read, write, and execute, with '-' indicating no permission.

The octal form condenses this into three digits, one for each user class (owner, group, others), calculated by adding the values of enabled permissions. For instance, 755 grants the owner full access (7), while group and others get read and execute (5).

The 777 example shows full access for all, which is rare due to security risks, while 644 is common for files needing owner editing and public reading.

Octal permission values

This table provides a detailed look at how octal values are calculated from permission combinations, showing every possible value from 0 to 7 with their symbolic, binary, and descriptive equivalents.

Octal Permission Calculations
Octal Value Symbolic Notation Binary Representation Calculation Description
0 --- 000 0 No permissions
1 --x 001 1 Execute only
2 -w- 010 2 Write only
3 -wx 011 2 + 1 = 3 Write and Execute
4 r-- 100 4 Read only
5 r-x 101 4 + 1 = 5 Read and Execute
6 rw- 110 4 + 2 = 6 Read and Write
7 rwx 111 4 + 2 + 1 = 7 Read, Write, and Execute (full permissions)

The octal system simplifies permission settings by assigning values to each permission: read (4), write (2), and execute (1). These are added together to form a single digit per user class.

The binary representation (e.g., 101 for 5) mirrors this, with each bit corresponding to a permission (1 for enabled, 0 for disabled). For example, 5 (read and execute) is rare for files but common for directories, while 6 (read and write) suits editable documents.

This table is a reference for constructing any permission string, like combining rw- (6) for an owner with r-- (4) for others in 644.

Special permissions

Besides the nine basic bits, there are three special permission bits. They are set with a fourth, leading octal digit, for example chmod 2775.

Viewing file permissions

The ls -l command shows the permissions in the first column of its long listing.

ls -l report.txt backup.sh
ls -ld docs
stat -c '%A %a %U:%G %n' report.txt docs

In -rw-r--r--, the first character is the file type: - for a regular file, d for a directory, and l for a symbolic link. The next nine characters are the permissions of the owner (rw-), the group (r--), and others (r--). The two names that follow are the owner and the group. The -d option shows the directory itself instead of its contents. The stat command can also print the permissions in octal form.

$ ls -l report.txt backup.sh
-rw-r--r-- 1 jano jano 35 Oct 23 09:00 backup.sh
-rw-r--r-- 1 jano jano 18 Oct 23 09:00 report.txt
$ ls -ld docs
drwxr-xr-x 2 jano jano 4096 Oct 23 09:00 docs
$ stat -c '%A %a %U:%G %n' report.txt docs
-rw-r--r-- 644 jano:jano report.txt
drwxr-xr-x 755 jano:jano docs

Changing permissions in numeric mode

The chmod command changes permissions. In numeric mode, it sets all permission bits at once.

chmod 755 backup.sh

A newly created script cannot be run because it lacks the execute permission. The mode 755 sets rwx (7) for the owner and r-x (5) for the group and others. Numeric mode is absolute: the previous permissions are replaced. Only the owner of a file or root can change its permissions.

$ ./backup.sh
bash: ./backup.sh: Permission denied
$ chmod 755 backup.sh
$ ls -l backup.sh
-rwxr-xr-x 1 jano jano 35 Oct 23 09:00 backup.sh
$ ./backup.sh
backup complete

Changing permissions in symbolic mode

Symbolic mode modifies selected permissions and leaves the others unchanged. It combines the classes u, g, o, and a (all) with an operator and permissions.

chmod g+w team_doc.txt
chmod u=rw,g=r,o= notes.txt
chmod a-w notes.txt

The + operator adds permissions, - removes them, and = sets them exactly; o= removes all permissions of others. Several clauses are separated by commas. After a-w, nobody can write to the file, so the redirection fails.

$ chmod g+w team_doc.txt
$ ls -l team_doc.txt
-rw-rw-r-- 1 jano jano 6 Oct 23 09:00 team_doc.txt
$ chmod u=rw,g=r,o= notes.txt
$ ls -l notes.txt
-rw-r----- 1 jano jano 5 Oct 23 09:00 notes.txt
$ chmod a-w notes.txt
$ ls -l notes.txt
-r--r----- 1 jano jano 5 Oct 23 09:00 notes.txt
$ echo "more" >> notes.txt
bash: notes.txt: Permission denied

Directory permissions

For directories, the read permission allows listing the names of entries, while the execute permission allows accessing the entries.

chmod u-x private
chmod u+x,u-r private

Without the execute permission, we can list the file names in private, but we cannot read the file inside. Without the read permission but with execute, the listing fails, yet a file whose name we know can still be opened. The write permission on a directory, together with execute, allows creating, renaming, and deleting files in it, regardless of the permissions of those files.

$ mkdir private; echo "secret" > private/key.txt
$ chmod u-x private
$ ls -ld private
drw-r-xr-x 2 jano jano 4096 Oct 23 10:42 private
$ cat private/key.txt
cat: private/key.txt: Permission denied
$ ls private
key.txt
$ chmod u+x,u-r private
$ ls private
ls: cannot open directory 'private': Permission denied
$ cat private/key.txt
secret

Changing ownership

The chown command changes the owner and group of a file; chgrp changes only the group.

sudo chown alice:devs project.c
chgrp devs report.txt

The groups command shows that the current user is a member of the devs group. The syntax owner:group changes both at once, and :group changes only the group. Changing the owner requires root privileges, so a regular user cannot give a file away. The owner of a file can change its group to any group they belong to.

$ groups
jano devs
$ ls -l project.c
-rw-r--r-- 1 jano jano 10 Oct 23 09:00 project.c
$ sudo chown alice:devs project.c
$ ls -l project.c
-rw-r--r-- 1 alice devs 10 Oct 23 09:00 project.c
$ chown alice report.txt
chown: changing ownership of 'report.txt': Operation not permitted
$ chgrp devs report.txt
$ ls -l project.c report.txt
-rw-r--r-- 1 alice devs 10 Oct 23 09:00 project.c
-rw-r--r-- 1 jano  devs 18 Oct 23 09:00 report.txt

Using special permissions

We look at existing special permissions and set the SetGID bit on a shared directory.

ls -l /usr/bin/passwd
ls -ld /tmp
sudo mkdir /srv/team
sudo chgrp devs /srv/team
sudo chmod 2775 /srv/team

The passwd program has the SetUID bit, so it runs as root and can update the password database. The /tmp directory is world-writable but has the sticky bit, so users cannot delete each other's files. On /srv/team, the SetGID bit makes new files belong to the devs group even when created by root. A capital S or T means that the special bit is set without the underlying execute permission, which is usually a mistake.

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68248 Apr  7  2025 /usr/bin/passwd
$ ls -ld /tmp
drwxrwxrwt 1 root root 4096 Oct 23 10:42 /tmp
$ sudo mkdir /srv/team
$ sudo chgrp devs /srv/team
$ sudo chmod 2775 /srv/team
$ ls -ld /srv/team
drwxrwsr-x 2 root devs 4096 Oct 23 10:42 /srv/team
$ sudo touch /srv/team/plan.txt
$ ls -l /srv/team
total 0
-rw-r--r-- 1 root devs 0 Oct 23 10:42 plan.txt
$ chmod u+s report.txt
$ ls -l report.txt
-rwSr--r-- 1 jano devs 18 Oct 23 09:00 report.txt

Default permissions with umask

The umask determines the permissions of newly created files and directories. Its bits are removed from the default modes, which are 666 for files and 777 for directories.

umask
umask -S
umask 027

The common umask 022 removes the write permission for the group and others, giving 644 for files and 755 for directories. With 027, new files get 640 and directories 750, so others have no access. The -S option shows the permissions that remain in symbolic form. The setting applies to the current shell; to make it permanent, put it in ~/.bashrc or ~/.profile.

$ umask
0022
$ umask -S
u=rwx,g=rx,o=rx
$ umask 027
$ touch new.txt; mkdir newdir
$ ls -ld new.txt newdir
drwxr-x--- 2 jano jano 4096 Oct 23 10:42 newdir
-rw-r----- 1 jano jano    0 Oct 23 10:42 new.txt

Changing permissions recursively

The -R option applies chmod to a directory and all its contents.

chmod -R u=rwX,go=rX site
find site -type f -exec chmod 600 {} +

A recursive numeric mode such as chmod -R 755 would make all regular files executable. The capital X adds the execute permission only to directories and to files that are already executable for someone. For finer control, find selects the files by type and runs chmod on them.

$ mkdir -p site/css site/js; touch site/index.html site/css/main.css site/js/app.js
$ chmod -R u=rwX,go=rX site
$ find site -exec stat -c "%A %n" {} +
drwxr-xr-x site
drwxr-xr-x site/css
-rw-r--r-- site/css/main.css
drwxr-xr-x site/js
-rw-r--r-- site/js/app.js
-rw-r--r-- site/index.html
$ find site -type f -exec chmod 600 {} +
$ find site -type f -exec stat -c "%A %n" {} +
-rw------- site/css/main.css
-rw------- site/js/app.js
-rw------- site/index.html

Finding files by permissions

The -perm test of find searches for files with given permissions.

find . -perm -o+w
find . -type f -perm 600
find /usr/bin -perm -4000

With a leading -, the listed bits must all be set, while other bits are ignored; the first command finds world-writable files. Without a prefix, the permissions must match exactly. The last command lists the SetUID programs in /usr/bin, which is a common security audit check. When searching the whole system, add 2>/dev/null to hide errors for directories we cannot read.

$ chmod o+w notes.txt
$ find . -perm -o+w
./notes.txt
$ find . -type f -perm 600
./site/css/main.css
./site/js/app.js
./site/index.html
$ find /usr/bin -perm -4000
/usr/bin/chfn
/usr/bin/su
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/umount
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/sudo

Best practices for file permissions

Source

GNU file permissions documentation

In this article, we have explained Linux file permissions and used ls, chmod, chown, chgrp, umask, and find to view, change, and audit them.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Linux tutorials.