Mastering Linux File Permissions with the 'chmod' Command

Learn chmod with symbolic and numeric modes, safe defaults, recursive changes, and special permission bits.

Mastering Linux File Permissions with the 'chmod' Command

Linux file permissions decide who can read, change, or run a file. When a script will not execute, a web server cannot read a file, or a private key is rejected as too open, chmod is often part of the fix.

The chmod command changes permission bits. You can use readable symbolic modes like u+x or compact numeric modes like 755.

Read Permission Strings

Run ls -l to see a file's type and permissions:

ls -l deploy.sh

Example output:

-rwxr-xr-- 1 app deploy 1200 May 23 10:00 deploy.sh

The first character is the file type. A regular file starts with -, a directory starts with d, and a symbolic link starts with l.

The next nine characters are three permission groups:

  • User: the file owner.
  • Group: members of the file's group.
  • Others: everyone else.

Each group can have:

  • r: read file contents, or list directory names.
  • w: modify a file, or create/delete/rename entries in a directory.
  • x: execute a file, or traverse a directory.

Directory execute permission matters. Without x on a directory, you cannot enter it or access files inside it by name, even if you can list some metadata elsewhere.

Use Symbolic Modes for Small Changes

Symbolic syntax looks like this:

chmod [who][operator][permissions] path

who can be u for user, g for group, o for others, or a for all. Operators are + to add, - to remove, and = to set exactly.

Make a script executable for the owner:

chmod u+x deploy.sh

Allow the group to edit a shared file:

chmod g+w shared_document.txt

Remove write access from group and others:

chmod go-w config.yml

Set others to read-only, replacing any existing permissions for others:

chmod o=r project_plan.txt

Symbolic modes are useful because they change only the bits you name.

Use Numeric Modes for Full Permission Sets

Numeric modes set user, group, and other permissions in one command. Each permission has a value:

  • Read: 4
  • Write: 2
  • Execute: 1

Add the values for each group:

Mode Meaning
7 rwx
6 rw-
5 r-x
4 r--
0 ---

Set a normal text file to owner read/write and everyone else read-only:

chmod 644 important_file.txt

Set a normal directory so the owner can manage it and others can enter and read it:

chmod 755 public_assets

Lock down a private key so only the owner can read and write it:

chmod 600 private_key.pem

Avoid 777 unless you are in a temporary test environment and understand the risk:

chmod 777 scratch

777 lets any local user read, write, and execute or traverse the path. On shared systems, that is rarely acceptable.

Handle Files and Directories Differently

Files and directories usually need different modes. Files often use 644; directories often use 755. If you run this blindly, you make every file executable:

chmod -R 755 web_root/

For a web directory, a safer pattern is:

find web_root -type d -exec chmod 755 {} +
find web_root -type f -exec chmod 644 {} +

Then add execute permission only to scripts that actually need it:

chmod 755 web_root/scripts/deploy.sh

Use Special Permission Bits Carefully

Numeric modes can include a fourth leading digit for special bits:

Value Name Common effect
4 SetUID An executable runs with the file owner's effective user ID.
2 SetGID An executable runs with the file group's effective group ID; on directories, new entries inherit the directory's group.
1 Sticky bit On directories, users can delete only files they own, the directory owner owns, or root can delete.

Set the SetGID bit on a shared project directory so new files inherit the directory group:

chmod 2770 shared_group_files

Set the sticky bit on a shared writable directory:

chmod 1777 /srv/shared-upload

The classic example is /tmp, which is world-writable but protected by the sticky bit.

Be cautious with SetUID and SetGID on executables. They can create serious privilege-escalation risk if the program is writable, poorly designed, or accepts unsafe input. Many Unix-like systems also ignore SetUID on scripts for security reasons.

Verify the Result

After changing permissions, check them:

ls -ld web_root web_root/index.html

Use stat when you want the numeric mode:

stat -c '%a %n' web_root/index.html

On macOS, the stat format is different:

stat -f '%Lp %N' web_root/index.html

Takeaway

Use symbolic chmod when you want to add or remove one permission. Use numeric chmod when you want to set the full mode exactly. Treat recursive changes with care, keep files and directories separate, and verify with ls -l or stat before you move on.