How the chmod command works on linux
Tags: linux, webdev, codenewbie, tutorial
Published: 2022-03-11 16:30:08

When we create a file or folder on a unix based system like Linux or MacOS, it has a set of permissions and access modes. These are most often manipulated using the chmod command, which allow us to change who can access and run different files.

Let's look at how chmod works. To begin, the chmod command has the following syntax, where `[OPTIONS]` are optional settings, `[MODE]` are the permissions we want to give the file or folder, and `x` is the file we want to apply chmod to.

```
chmod [OPTIONS] [MODE] x
```

## How the file permission works on Linux and MacOS
Before we start to use chmod, let's look at how permission works on Linux and MacOS. If you go into any folder, and run `ls -l`, you'll see a line like this:

```
drwxr-xr-x 5 root root 160 23 Feb 22:32 node_modules
```

The first part of this line is the permission settings - that is, `drwxr-xr-x`. Let's break down what this means:

```
d  rwx  r-x  r-x
^   ^    ^    ^
|   |    |    |
|   |    |    └ - -  the permission of "others", i.e. anyone who is not an owner or a group
|   |    └ - - the group's permissions 
|   └ - - the owner's permissions
└ - - File type - is not related to access
```

Above, "others", refers to anyone who is not an owner or group of users. If you are wondering who the owner and group are, they are the two names given after the number 5 in our example:

```
drwxr-xr-x 5 root root 160 23 Feb 22:32 node_modules
|--------|   |--| |--|
^            ^    ^
|            |    |
|            |    └ - - group
|            └ - - owner
└ - - permission settings
```

## What permissions mean in Linux and MacOS
In our permissions above, we have 3 sets of access - `rwx`, `r-x`, and `r-x`. Each letter represents a type of access. If one letter is missing, that set of individuals or owner does not have that access. The letters stand for:

- **r** - read access
- **w** - write or edit access
- **x** - execute access (for files that are executable
- **t** - a sticky bit, which means only the owner or root user can delete or rename the file or folder. This is appended to the end of the permission string, if it exists, and is less common than the others.
- **s** - gives escalated privileges for execution to users or groups.

So while `rwx` gives read, write and execute access, `r-x` only gives read and execute access.

## How to use chmod in Linux and MacOS
Now that we've covered the fundamentals, let's look at how chmod works. The formatting of chmod can be a little confusing when you first see it, so let's break it down.

We first start by mentioning which users are affected. We have 4 options here:

- **u**, for the owner
- **g**, for the group
- **o**, for others
- **a**, for all, which can also be written as `ugo`.

This is then followed by how we want to change permissions:

- If we want to give permissions to a set of users or user, we write `+`, so `+x` will give execute permission, and `+rx` will give read and execute permission.
- If we want to revoke permissions, we write `-`, so `-rwx` takes away read, write and execute access.
- If we want to replace permissions entirely, we use `=`, so `=r` will give read access, but remove execute and write if they existed. Similarly, `=rw` is the same as read and write access, with execute removed if it existed.

We write these all with no spaces, followed by the file name. So the following will give an owner read access to a file called file.txt, in the current directory:

```
chmod u+r file.txt
```

Or if we want to give the owner, group, and other users access to read and write, we could write the following:

```
chmod ugo+rw file.txt
```

Similarly, the following will replace the owner and groups permissions with read and write access, but remove any execute permission they may have had:

```
chmod ug=rw file.txt
```

If we want to give separate access types to different users, we can separate them with a comma. The below will give the owner `rwx` access, the group, `rw-` access, and all others `r--` access:

```
chmod u=rwx,g=rw,o=r file.txt
```

And if we don't write anything after equals sign, it is assumed all access is revoked. So, if instead, we want the group to have no access, we could write the following:

```
chmod u=rwx,g=,o=r file.txt
```

This also works with directories, in the same way that it does with our file.txt

## How to recursively change a directory's mode with chmod
Sometimes, we want to not only change a directory's permissions, but also all files within it. For that, we can use the `-R` option with chmod to recursively change the every file and folder within a directory.

Here is an example:

```
chmod -R u=rwx myDirectory
```

## Changing file mode with chmod using numbers
You may have seen chmod being used with numbers, rather than letters. The numbers ultimately follow the same convention as above, but are much simpler to write out. Each user permission in `rwx` is given a certain value:

- **r** is given a value of 4
- **w** is given a value of 2
- **x** is given a value of 1

That means a total value of `7` means `4 + 2 + 1`, or `rwx`. A value of `5` would mean `4 + 1`, or `r-x`. We can assign the owner, group, and other users a number each. So given a permission set like this:

```
rwx  r-x  --x
^    ^    ^
|    |    |
|    |    └ - -  the permission of "others", i.e. anyone who is not an owner or a group
|    └ - - the group's permissions 
└ - - the owner's permissions
```

The owner has a permission value of `7`, the group has `5`, and any other users have a permission of `1`. So we can write this as `751`.

To apply these permissions to our file, file.txt, then, we can write the following:

```
chmod 751 file.txt
```

### Adding Sticky bits to numeric permissions with chmod
To add a sticky bit to a numeric permission, we just add a a `1` to the start, so permissions `755` with a sticky bit become `1755`.

For many, numeric permissions are preferred as they are much cleaner and easier to understand than the letters. Whichever you prefer, both work in the same way, so choose depending on your own preference.