How to Change File Permissions Using chmod

Learn how to use chmod to change Linux file permissions using both symbolic (u+x, g-w) and numeric (755, 644) modes, with practical examples and common use cases.

How to Change File Permissions Using chmod

chmod (change mode) is the Linux command for changing file permissions. It works in two modes: symbolic mode uses letters like chmod u+x file (add execute for owner) or chmod go-w file (remove write for group and others), while numeric mode uses octal numbers like chmod 755 file (rwxr-xr-x) or chmod 644 file (rw-r–r–). To change permissions recursively for an entire directory, add the -R flag: chmod -R 755 directory/.

Introduction: Taking Control of File Permissions

You now know what Linux file permissions are — the nine bits that control read, write, and execute access for the owner, group, and others. But knowing what permissions mean and knowing how to change them are two separate skills. chmod is the command that bridges that gap.

chmod (change mode) is one of the most frequently used commands in Linux administration. You use it every time you write a shell script and need to make it executable. You use it to protect configuration files that contain passwords. You use it to set up shared directories where a team can collaborate. You use it during web server setup to ensure the right processes can read the right files. Understanding chmod thoroughly — both its modes, its syntax, and the judgment of which permissions to set — is a core Linux competency.

This article covers chmod completely: both notation systems (symbolic and numeric/octal), recursive permission changes, special permission bits (SetUID, SetGID, sticky bit), common real-world permission patterns, and how to avoid the most common chmod mistakes. By the end, you will be able to read any permission requirement and translate it into the right chmod command confidently.

chmod Basics: The Two Modes

chmod offers two completely different ways to specify permissions: symbolic mode (using letters) and numeric mode (using octal numbers). Both accomplish the same thing — setting permission bits — but each has advantages in different situations. Most experienced Linux users use both fluidly.

Symbolic Mode: Human-Readable Changes

Symbolic mode describes permission changes in terms of who, what operation, and which permissions:

Bash
chmod [who][operator][permissions] file

Who:

  • u — user (the file’s owner)
  • g — group (the file’s associated group)
  • o — others (everyone else)
  • a — all (u + g + o combined)

Operator:

  • + — add the specified permission(s)
  • - — remove the specified permission(s)
  • = — set exactly these permission(s), removing all others for that class

Permissions:

  • r — read
  • w — write
  • x — execute
  • X — execute only if the file is a directory or already has execute for someone (useful with -R)
  • s — SetUID (for u) or SetGID (for g)
  • t — sticky bit (for o)

Symbolic mode examples:

Bash
$ chmod u+x sc.ript.sh           # Add execute for owner
$ chmod g-w shared_file.txt     # Remove write for group
$ chmod o-r private.txt         # Remove read for others
$ chmod a+r public_doc.pdf      # Add read for everyone
$ chmod u+x,g+r new_sc.ript.sh   # Multiple changes at once
$ chmod go-rwx secret.key       # Remove all permissions for group and others
$ chmod u=rw,go=r config.txt    # Set owner to rw, group and others to r
$ chmod a-x binary_data.bin     # Remove execute from everyone

The = operator is particularly useful for setting exact permissions without worrying about what was there before:

Bash
$ chmod u=rwx,g=rx,o=r sc.ript.sh    # Precisely set all three classes

Numeric Mode: Precise Octal Notation

Numeric mode expresses the complete permission set as a three-digit octal number. Each digit represents one permission class (owner, group, others), and each digit is the sum of the active permission bits:

  • Read (r) = 4
  • Write (w) = 2
  • Execute (x) = 1

Calculate each digit by adding the values of the permissions you want:

PermissionsCalculationDigit
rwx4+2+17
rw-4+2+06
r-x4+0+15
r--4+0+04
-wx0+2+13
-w-0+2+02
--x0+0+11
---0+0+00

A three-digit chmod command like chmod 754 file sets:

  • Owner (7): rwx (4+2+1)
  • Group (5): r-x (4+0+1)
  • Others (4): r-- (4+0+0)

Numeric mode examples:

Bash
$ chmod 755 sc.ript.sh       # rwxr-xr-x  (standard executable)
$ chmod 644 document.txt    # rw-r--r--  (standard file)
$ chmod 600 private.key     # rw-------  (private file)
$ chmod 700 secret_dir/     # rwx------  (private directory)
$ chmod 664 team_notes.txt  # rw-rw-r--  (group-writable)
$ chmod 775 project_dir/    # rwxrwxr-x  (group-writable directory)
$ chmod 400 readonly.conf   # r--------  (read-only even for owner)
$ chmod 000 locked.txt      # ---------- (no permissions for anyone)

Which Mode to Use?

Use symbolic mode when:

  • Making incremental changes to existing permissions (adding or removing specific bits)
  • You do not want to affect permissions you are not explicitly changing
  • Writing self-documenting scripts where the intent should be clear
Bash
$ chmod +x sc.ript.sh          # Clear intent: make executable
$ chmod o-r private.txt       # Clear intent: remove public read

Use numeric mode when:

  • Setting complete, absolute permissions from scratch
  • You want to set all three permission classes precisely at once
  • Speed matters — numeric mode is faster to type for common combinations
  • Following documented permission requirements (documentation often specifies “set permissions to 644”)
Bash
$ chmod 755 sc.ript.sh         # Fast, precise, exact
$ chmod 600 ~/.ssh/.id_rsa     # Clear known-good pattern

Viewing Current Permissions

Always check current permissions before and after changing them to confirm the result:

Bash
$ ls -la filename
-rw-r--r-- 1 sarah developers 2048 Feb 18 10:15 report.txt

$ chmod 664 report.txt

$ ls -la filename
-rw-rw-r-- 1 sarah developers 2048 Feb 18 10:15 report.txt

The permission string changed from -rw-r--r-- to -rw-rw-r--, confirming that group write was added successfully.

Using stat for Detailed Permission Information

Bash
$ stat report.txt
  File: report.txt
  Size: 2048      	Blocks: 8          IO Block: 4096   regular file
Device: 802h/2050d	Inode: 1234567     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/   sarah)   Gid: ( 1001/developers)
Access: 2026-02-18 10:15:22.000000000 +0000
Modify: 2026-02-18 10:15:22.000000000 +0000
Change: 2026-02-18 10:22:05.000000000 +0000

stat shows both the octal form (0664) and symbolic form (-rw-rw-r--) of the current permissions — useful for translating between the two notations.

Recursive Permissions with -R

The -R (recursive) flag applies the permission change to a directory and all its contents — every file and subdirectory within it:

Bash
$ chmod -R 755 project/

This sets 755 on the project/ directory itself, all files inside it, and all subdirectories and their contents.

The Problem with Naive Recursive chmod

Using a single permission set recursively on a directory often does the wrong thing for files. Directories need execute permission (to traverse into them), but regular files usually should not be executable:

Bash
$ chmod -R 755 website/

This sets rwxr-xr-x on every file — including text files, images, and HTML files that should never be executable. This is unnecessary (harmless for most files but untidy) and potentially a security concern for web-served files.

The Right Approach: Separate File and Directory Permissions

Use find with -exec to apply different permissions to files and directories:

Bash
# Set directories to 755 (rwxr-xr-x)
$ find project/ -type d -exec chmod 755 {} +

# Set regular files to 644 (rw-r--r--)
$ find project/ -type f -exec chmod 644 {} +

This cleanly separates concerns: directories get traversal permission, files get appropriate access without the execute bit.

For a group-collaborative setup:

Bash
# Directories: rwxrwxr-x (group can create/delete files)
$ find project/ -type d -exec chmod 775 {} +

# Files: rw-rw-r-- (group can read and write)
$ find project/ -type f -exec chmod 664 {} +

The X Permission: Smart Execute

The uppercase X in symbolic mode adds execute permission only to:

  • Directories (always)
  • Files that already have execute permission set for at least one class
Bash
$ chmod -R a+X project/

This adds execute where it makes sense (directories and already-executable files) without adding execute to regular data files. It is a cleaner recursive approach than simply using +x on everything.

Setting Special Permission Bits with chmod

Beyond the nine standard permission bits, chmod also sets the three special permission bits: SetUID, SetGID, and the sticky bit.

SetUID: Run as the File’s Owner

SetUID on an executable file causes it to run with the file owner’s permissions, not the caller’s:

Symbolic:

Bash
$ chmod u+s program

Numeric: Add 4000 as a fourth (leading) digit:

Bash
$ chmod 4755 program    # rwsr-xr-x

The s in the owner execute position confirms SetUID is set.

If the file does not have execute permission for the owner, the SetUID bit is shown as S (capital) instead of s:

Bash
$ chmod 4644 program    # rwSr--r-- (SetUID set but no execute — unusual/unintended)

SetGID: Inherit the File’s Group

SetGID on an executable runs with the file’s group identity. SetGID on a directory causes new files created in it to inherit the directory’s group rather than the creator’s primary group:

Symbolic:

Bash
$ chmod g+s directory/

Numeric: Add 2000 as a leading digit:

Bash
$ chmod 2775 directory/    # rwxrwsr-x

The s in the group execute position confirms SetGID is set.

The complete collaborative directory setup with SetGID:

Bash
$ sudo mkdir /shared/project
$ sudo chown alice:developers /shared/project
$ sudo chmod 2775 /shared/project
$ ls -la /shared/
drwxrwsr-x 2 alice developers 4096 Feb 18 11:00 project

Now any developer who creates a file in /shared/project will have that file automatically owned by the developers group.

Sticky Bit: Protect Files in Shared Directories

The sticky bit on a directory means only the file’s owner (or root) can delete or rename files within it, even if the directory is world-writable. The /tmp directory uses this pattern:

Symbolic:

Bash
$ chmod o+t /shared/tmp_area/
$ chmod +t /shared/tmp_area/     # +t without specifying who also sets sticky

Numeric: Add 1000 as a leading digit:

Bash
$ chmod 1777 /shared/tmp_area/    # rwxrwxrwt

The t in the others execute position confirms the sticky bit is set.

Using the Four-Digit Octal Form

For clarity and completeness, always use the four-digit form when setting special bits:

PermissionFour-DigitString
SetUID + rwxr-xr-x4755rwsr-xr-x
SetGID + rwxrwxr-x2775rwxrwsr-x
Sticky + rwxrwxrwx1777rwxrwxrwt
SetUID + SetGID6755rwsr-sr-x

Three-digit commands like chmod 755 implicitly have a leading 0 (0755), meaning no special bits. Using chmod 2775 explicitly sets SetGID along with the standard permissions.

Common Permission Patterns and When to Use Them

644 — Standard File

Bash
$ chmod 644 document.txt    # rw-r--r--

Owner reads and writes. Group and others read only. The default permission for most personal files, documents, and configuration files you want others to be able to read.

600 — Private File

Bash
$ chmod 600 ~/.ssh/.id_rsa    # rw-------

Owner reads and writes only. No access for anyone else. Use for private keys, password files, and sensitive configuration.

755 — Standard Executable or Public Directory

Bash
$ chmod 755 sc.ript.sh        # rwxr-xr-x
$ chmod 755 /var/www/html/   # rwxr-xr-x

Owner has full access. Group and others can read and execute (traverse for directories). Use for programs meant for general use and public directories.

700 — Private Directory or Script

Bash
$ chmod 700 ~/private/       # rwx------
$ chmod 700 admin_sc.ript.sh  # rwx------

Only the owner can access. Use for directories with sensitive content and scripts only the owner should run.

664 — Group-Writable File

Bash
$ chmod 664 team_notes.txt   # rw-rw-r--

Owner and group members can read and write. Others can read. Use for files shared within a team where multiple people need to edit.

775 — Group-Writable Directory

Bash
$ chmod 775 /projects/team/  # rwxrwxr-x

Owner and group members have full directory access. Others can read and traverse. Use for shared project directories.

770 — Private Group Directory

Bash
$ chmod 770 /projects/secret/    # rwxrwx---

Owner and group members have full access. Others have no access. Use for directories where sensitive team content should not be publicly readable.

400 and 444 — Read-Only Files

Bash
$ chmod 400 important_archive.tar.gz    # r--------
$ chmod 444 template.conf               # r--r--r--

400 — only the owner can read (maximum protection). 444 — everyone can read but nobody can write. Use for files that should never be modified accidentally.

chmod in Practice: Real-World Scenarios

Making a Script Executable

The most common chmod use case:

Bash
$ nano de.ploy.sh
# [write your script]
$ chmod +x de.ploy.sh      # or chmod 755 deploy.sh
$ ./de.ploy.sh

Without the chmod step, running ./de.ploy.sh produces “Permission denied” even though you own the file.

Fixing SSH Key Permissions

The SSH client refuses to use key files with overly permissive permissions:

Bash
$ chmod 700 ~/.ssh/          # SSH directory
$ chmod 600 ~/.ssh/.id_rsa    # Private key
$ chmod 644 ~/.ssh/.id_rsa.pub  # Public key (shareable)
$ chmod 600 ~/.ssh/.config    # SSH config file
$ chmod 600 ~/.ssh/.authorized_keys  # Authorized keys

After setting these, the SSH “UNPROTECTED PRIVATE KEY FILE” warning disappears.

Setting Up a Web Server Document Root

Web server files need to be readable by the web server process (www-data) but should not be world-writable:

Bash
$ sudo chown -R developer:www-data /var/www/html/
$ sudo find /var/www/html -type d -exec chmod 750 {} +
$ sudo find /var/www/html -type f -exec chmod 640 {} +

Directories: 750 — developer has full control, www-data can read and traverse, others nothing. Files: 640 — developer can read/write, www-data can read (serve the files), others nothing.

Protecting a Configuration File with Secrets

Bash
$ sudo chmod 600 /etc/app/data.base.conf    # rw-------
$ sudo chown appuser:appuser /etc/app/database.conf

Only appuser (and root) can read the configuration containing the database password.

Setting Up a Shared Scratch Directory

A temporary work directory where multiple users can create files but cannot delete each other’s:

Bash
$ sudo mkdir /shared/scratch
$ sudo chmod 1777 /shared/scratch    # rwxrwxrwt

The sticky bit (1777) allows anyone to create files but only the file’s owner can delete them — the same pattern used by /tmp.

chmod Pitfalls and How to Avoid Them

Pitfall 1: chmod -R with a Single Permission Set

The problem:

Bash
$ chmod -R 755 website/

This sets execute permission on all files including HTML, CSS, images, and text files that should not be executable. While not dangerous for most files, it is messy and occasionally a security concern.

The solution: Use separate find commands for files and directories:

Bash
$ find website/ -type d -exec chmod 755 {} +
$ find website/ -type f -exec chmod 644 {} +

Pitfall 2: Forgetting the Execute Bit on a Directory

Bash
$ chmod 644 mydir/

This removes execute (traverse) permission from the directory. Now nobody (not even the owner) can cd into mydir/ or access files within it, even if those files have permissive permissions.

The solution: Directories almost always need execute permission: chmod 755 mydir/ not chmod 644 mydir/.

Pitfall 3: Making Files World-Writable

Bash
$ chmod 777 file.txt    # DANGEROUS

World-writable files (rwxrwxrwx) can be modified by any user on the system. This is almost never the right solution. If you need group sharing, use 664 or 775. If you need a world-writable area, use sticky bit (1777) on a directory.

Pitfall 4: Running chmod Recursively as Root Without Checking

Bash
$ sudo chmod -R 777 /important/system/directory/    # VERY DANGEROUS

Running chmod -R as root on the wrong directory can damage system files or security-sensitive files. Always double-check the path before running recursive chmod as root. Add --dry-run where supported, or use ls -la to preview the target first.

Pitfall 5: chmod Without Matching chown

Setting permissions on a file owned by the wrong user does not make it accessible. Permissions are evaluated relative to the file’s owner and group — if you own neither, only the “others” bits apply regardless of how permissive owner and group bits are.

Always consider whether chown or chgrp is also needed when fixing permission problems.

Quick Reference: chmod Cheat Sheet

Symbolic Mode

CommandEffect
chmod +x fileAdd execute for all
chmod u+x fileAdd execute for owner
chmod g+w fileAdd write for group
chmod o-r fileRemove read for others
chmod go-w fileRemove write for group and others
chmod a-x fileRemove execute for everyone
chmod u=rwx,go=rx fileSet owner to rwx, group/others to rx
chmod g+s dir/Set SetGID on directory
chmod +t dir/Set sticky bit
chmod u+s programSet SetUID on executable

Numeric Mode

ModeStringTypical Use
400r——–Read-only for owner only
600rw——-Private file (SSH keys, secrets)
644rw-r–r–Standard file
664rw-rw-r–Group-editable file
700rwx——Private executable or directory
755rwxr-xr-xStandard executable or public dir
775rwxrwxr-xGroup-editable directory
777rwxrwxrwxWorld-writable (avoid)
1777rwxrwxrwtWorld-writable with sticky (/tmp)
2775rwxrwsr-xSetGID collaborative directory
4755rwsr-xr-xSetUID executable

Conclusion: chmod as Precision Instrument

chmod is deceptively simple on the surface — a command with two notation systems and a handful of flags. But used skillfully, it is a precision instrument for expressing exactly the access control policy each file and directory needs.

The key insights to carry forward: symbolic mode (chmod u+x) is cleaner for incremental changes and self-documenting scripts; numeric mode (chmod 755) is faster for setting complete permissions. Recursive chmod (-R) should almost always separate files from directories using find. Special bits (SetGID in particular) are essential for collaborative directories where files should automatically inherit group ownership. And every permission decision should be the minimum necessary — files should not be executable unless they need to be, group-writable unless sharing requires it, world-accessible unless public access is the intent.

With chmod and the permission system fully understood, you have genuine control over who can do what with every file on your Linux system — and the tools to enforce that control precisely and deliberately.

Share:
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments

Discover More

Cable Management in Robotics: Preventing Tangles and Breaks

Cable Management in Robotics: Preventing Tangles and Breaks

Master cable management in robotics—learn routing, strain relief, connector selection, and wire labeling techniques to…

What is a DataFrame? The Foundation of Data Science

Learn what a DataFrame is and why it’s essential for data science. Complete guide covering…

Understanding the Cost Function in Linear Regression

Learn what the cost function is in linear regression, why MSE is used, how it…

ROC Curves and AUC: Evaluating Classification Models

ROC Curves and AUC: Evaluating Classification Models

Learn how ROC curves and AUC scores evaluate classification models. Understand TPR, FPR, threshold selection,…

Introduction to Logistic Regression

Learn Logistic Regression in-depth, from its working principles to advanced applications. Master classification algorithms for…

Visualizing Mathematical Concepts with Matplotlib

Master Matplotlib for machine learning visualization. Learn to create line plots, scatter plots, histograms, heatmaps,…

Click For More
0
Would love your thoughts, please comment.x
()
x