Linux Chmod Complete Guide: Octal, Symbolic & Recursive Examples

By G.Bharat Kumar | Published on 2026-06-29

Introduction

If you have spent any significant amount of time working with Linux, macOS, or any Unix-like operating system, you have undoubtedly encountered the chmod command. Standing for "change mode," chmod is one of the most fundamental, powerful, and occasionally misunderstood commands in a system administrator's or developer's toolkit. Whether you are trying to make a bash script executable, fixing a broken web server directory, or securing sensitive configuration files, understanding how to change file permissions in Linux is an absolute requirement for mastering the command line environment.

This sub-guide is designed to take you on a deep dive strictly into the chmod command itself. Before proceeding, we highly recommend you first understand the foundational concepts covered in our overarching Linux Permissions Complete Guide. That pillar guide explains users, groups, and the basic theory behind Linux system security. Here, in this dedicated guide, we will roll up our sleeves and explore the exact commands, mathematics, and syntax you need to apply that theory in practical, real-world scenarios. We will explore everything from basic syntax to advanced enterprise security concepts.

Furthermore, we know that doing octal math in your head can be tedious, confusing, and prone to error—especially under the pressure of a broken production server. That is exactly why we built our interactive Chmod Calculator tool. If you ever find yourself struggling to figure out if you need chmod 755, chmod 644, or something much more obscure, you can use our visual calculator to instantly generate the correct numeric or symbolic command for your exact use case. We highly recommend bookmarking it for your daily workflow!

🚀 Quick Solution Box: Most Common Chmod Commands

Need the answer right now? Here are the most frequently used chmod commands across the software engineering industry:

  • Make a script executable:
    chmod +x script.sh
  • Standard Web File (Read/Write for owner, Read for others):
    chmod 644 config.php
  • Standard Web Directory (Accessible and listable):
    chmod 755 /var/www/html/assets/
  • Secure an SSH Key (Owner only, completely private):
    chmod 600 ~/.ssh/id_rsa
  • Dangerous/Insecure Full Access (Never use in production!):
    chmod 777 vulnerable_folder/

1. The History and Core Mechanics of Chmod

To truly appreciate the chmod command, it helps to understand its origins. Introduced in the very first versions of Unix in the early 1970s, chmod was created by pioneers like Dennis Ritchie and Ken Thompson. They needed a lightweight, mathematically elegant way to govern file access on multi-user mainframe computers. The system they designed has survived largely unchanged for over 50 years because of its profound simplicity and effectiveness.

At its core, the chmod command modifies the "permission bits" of a file or directory inode. In the Linux file system architecture, every single file has three distinct classes of users who can attempt to interact with it:

  • Owner (User - u): The individual who originally created the file or was explicitly assigned ownership via the chown command. The owner typically has the most control over the file.
  • Group (Group - g): A predefined collection of users who share a specific set of access rights. For example, a "developers" group might have access to source code files.
  • Others (World/All - o): Absolutely everyone else who has an account on the system or is accessing it anonymously (like a web server process).

For each of these three user classes, there are three fundamental permissions that can be independently granted or denied:

  • Read (r): The ability to view the textual or binary contents of a file. For directories, read access allows a user to list the names of the files contained within (like running the ls command).
  • Write (w): The ability to modify, alter, truncate, or append to a file. For directories, write access allows a user to create new files, rename existing files, or delete files within that directory.
  • Execute (x): The ability to command the operating system to run a file as a program or script. For directories, execute access is often referred to as the "search bit," allowing a user to cd (change directory) into it and access its metadata.

Viewing Permissions Before You Change Them

Before you use chmod to alter permissions, you must know how to check the current permissions. You do this using the long-format list command:

ls -l filename.txt

The output will look something like this: -rw-r--r-- 1 user group 1024 Jun 29 12:00 filename.txt. The very first block of characters (-rw-r--r--) represents the file mode. The first character denotes the type (a dash - for a file, a d for a directory). The next nine characters are broken into three blocks of three:

  1. rw- (Owner has Read and Write, but not Execute)
  2. r-- (Group has only Read)
  3. r-- (Others have only Read)

The chmod command provides two primary ways to manipulate these permissions: Octal (Numeric) Mode and Symbolic Mode. Both achieve the exact same underlying results, but they are suited to fundamentally different types of tasks. Octal mode is perfect for setting absolute permissions all at once, whereas symbolic mode is ideal for making relative adjustments.

2. Octal Mode: The Mathematics of Chmod

When you see commands like chmod 777, chmod 755, or chmod 644, you are looking at the Octal (base-8) representation of file permissions. It is by far the most common way developers, DevOps engineers, and system administrators share permission instructions, primarily because it is incredibly dense and concise. Instead of typing out a long string of letters and operators, you can comprehensively define the exact security posture of a file with just three numbers.

How Octal Permission Math Actually Works

In octal mode, each of the three permissions (Read, Write, Execute) is assigned a specific numeric value based on its binary bit representation. If you have a background in computer science, you will recognize these instantly as the binary powers of two:

  • Read (r) = 4 (Binary 100)
  • Write (w) = 2 (Binary 010)
  • Execute (x) = 1 (Binary 001)
  • No Permission (-) = 0 (Binary 000)

To figure out the final octal number for a specific user class (Owner, Group, or Other), you simply add the values of the permissions you want to grant together. Let's look at some detailed calculations.

If you want the Owner to have Read (4), Write (2), and Execute (1) permissions, you sum them:
4 + 2 + 1 = 7 (Full Access)

If you want the Group to have Read (4) and Execute (1) permissions, but absolutely no Write permission:
4 + 0 + 1 = 5 (Read and Execute)

If you want Others to have only Read (4) permission:
4 + 0 + 0 = 4 (Read Only)

By combining these three resulting numbers together sequentially, you get the three-digit octal permission code: 754. You would then apply this configuration to a file using the command:

chmod 754 filename.txt

Let's break down the most commonly used, industry-standard octal permission codes you will encounter in the wild, and explain precisely why they are used.

The Dangers of Chmod 777 (And Why You Shouldn't Use It)

Let's address the elephant in the room first. chmod 777 is the most infamous permission setting in the Linux ecosystem. What does it actually mean mathematically?

  • Owner: Read, Write, Execute (4+2+1 = 7)
  • Group: Read, Write, Execute (4+2+1 = 7)
  • Others: Read, Write, Execute (4+2+1 = 7)

In plain English, chmod 777 means absolutely anyone with access to the system can read, modify, delete, or execute this file or directory.

Junior developers and sysadmins often resort to using chmod 777 out of pure frustration. Imagine you are trying to upload a file via a PHP script, or trying to write logs from a Node.js application, and you continuously hit a brick wall: the dreaded Permission Denied error. In a moment of desperation, it is highly tempting to just run a recursive chmod 777 on the entire directory to make the error magically vanish. While this will undoubtedly "fix" the immediate functionality error, it completely destroys the security integrity of your system.

If your web application contains even a minor vulnerability, an attacker can use a 777-permissioned directory to upload malicious scripts (such as a PHP web shell), execute them directly via the browser, and take over your entire server. Similarly, in a shared hosting or multi-user environment, any other user on that physical machine can navigate to your 777 directory and maliciously modify, steal, or delete your data. You should almost never use chmod 777 in a production environment. If you find yourself needing to use it, you almost certainly have an ownership (chown) issue, not a permission issue. We will cover how to solve this correctly later in the guide.

The Standard for Directories: Chmod 755

The chmod 755 setting is the universally accepted gold standard for directories on Linux servers, particularly for web servers running Apache or Nginx.

  • Owner: Read, Write, Execute (4+2+1 = 7)
  • Group: Read, Execute (4+1 = 5)
  • Others: Read, Execute (4+1 = 5)

Why is this the industry standard? For a directory, the "Execute" bit has a special meaning: it is required in order for a user to cd into the directory and access the files contained within it. chmod 755 allows the owner (usually you, or the web server user) full administrative control to create, modify, and delete files within the directory. However, it tightly restricts everyone else (the group and others) to only being able to list the directory contents and read the files inside it. They cannot maliciously delete or overwrite your data, but they can view web pages.

The Standard for Files: Chmod 644

Just as 755 is the standard for directories, chmod 644 is the universally accepted standard for regular files (like HTML files, CSS stylesheets, PHP scripts, or basic configuration files).

  • Owner: Read, Write (4+2 = 6)
  • Group: Read (4)
  • Others: Read (4)

Notice that the Execute bit is completely absent across all user classes here. Standard web files and configuration documents do not need to be executed by the operating system; they only need to be read by the web server daemon or processed by an interpreter. The owner retains the ability to seamlessly edit (write) the file, while groups and others are strictly limited to reading it. This prevents unauthorized modifications while ensuring the file functions correctly when requested by a browser.

Highly Secure Scenarios: Chmod 600 and 400

For highly sensitive files, you must lock out everyone except the owner. Examples of these critical files include SSH private keys (like id_rsa or id_ed25519), database configuration files containing raw plaintext passwords (like wp-config.php in WordPress or .env files in Laravel), and SSL/TLS certificates.

chmod 600 (Owner: Read/Write, Group: None, Others: None) is the absolute mandatory standard for SSH keys. If you attempt to use an SSH private key with permissions that are too open (like 644 or 777), the SSH client will actually refuse to connect entirely. It will throw a fatal error stating "Permissions are too open," protecting you from yourself.

chmod 400 (Owner: Read Only, Group: None, Others: None) takes security a massive step further. It ensures that even the owner cannot accidentally overwrite or modify the file via a stray command or script without intentionally changing the permissions back first. This is excellent for immutable configuration files that should never change once provisioned.

3. Symbolic Mode: The Flexible Approach to Chmod

While octal mode is spectacular for setting absolute permissions (defining the entire security posture at once), it can be cumbersome if you only want to make a small, targeted change. What if a file has complex, bespoke permissions that you don't want to mentally calculate, and you simply want to make it executable for everyone? This is where Symbolic Chmod shines brightly.

Symbolic mode uses intuitive letters to define Who you are changing permissions for, What action you are taking, and Which permission you are modifying. The syntax structure looks like this:

chmod [Who][Operator][Permission] filename

The "Who" (User Classes)

  • u : User (the specific owner of the file)
  • g : Group (users who are members of the file's assigned group)
  • o : Others (everyone else on the system not covered by u or g)
  • a : All (a shortcut equivalent to specifying ugo together)

Pro Tip: If you omit the "Who" entirely (e.g., just typing chmod +x script.sh), the chmod command usually defaults to a (all). However, this default behavior can be affected and restricted by your system's underlying umask setting. To guarantee predictable results, it is always safer to explicitly state a if you truly mean all.

The "Operator" (Actions)

  • + : Adds the specified permission (leaves all other existing permissions untouched).
  • - : Removes the specified permission (leaves all other existing permissions untouched).
  • = : Sets the exact specified permission (ruthlessly overwrites and erases any previous permissions for that class).

The "Permission"

  • r : Read
  • w : Write
  • x : Execute
  • X : Special Execute (intelligently applies execute only to directories, not files)

Practical Symbolic Chmod Examples

Let's look at some real-world administration scenarios where symbolic mode is the undeniably superior tool of choice:

Scenario 1: Making a bash or python script executable.

You have just spent hours writing a backup script named backup.sh. You want to be able to run it via `./backup.sh`. You don't care what the current read/write permissions are, you just want to append the execute bit for yourself so you can test it.

chmod u+x backup.sh

If you want everyone on the system (perhaps a cron job running as another user) to be able to execute it:

chmod a+x backup.sh

Scenario 2: Revoking write access from the group.

You have a shared document, but you've decided that members of your group should only be able to read it, not modify it anymore. You want to remove the write bit for the group, leaving the owner's and others' access completely unchanged.

chmod g-w shared_doc.txt

Scenario 3: Locking down a file completely using equals (=).

You want to ensure that "others" have absolutely zero access to a highly sensitive file, regardless of what liberal permissions they might have had before. You can securely set their permissions to "nothing" by using the equals sign without any permission letters following it.

chmod o= secret_data.csv

Alternatively, you can force the group to be exactly read-only, aggressively overwriting whatever read/write/execute mishmash they had previously:

chmod g=r secret_data.csv

Scenario 4: Multi-class symbolic changes.

You can combine multiple discrete symbolic changes in a single command execution by separating them with commas. Crucially, do not put spaces after the commas. For example, to give the owner full read/write/execute, the group read/execute, and others read-only:

chmod u=rwx,g=rx,o=r application_binary

4. Recursive Chmod: Managing Directories in Bulk

When dealing with modern web applications, large source code repositories, or massive directories containing hundreds of thousands of files, running chmod on every single file manually is mathematically impossible. You need a fast, reliable way to apply permissions to a parent directory and have those changes propagate to all of the files and subdirectories nested deep within it. This action is known as Recursive Chmod.

You achieve this bulk operation by using the capital -R flag. (A crucial note: Linux is strictly case-sensitive. Using a lowercase -r will either result in an immediate syntax error or unexpected behavior, as -r is not the standard recursive flag for chmod).

Basic Recursive Example:

chmod -R 755 /var/www/html/myproject/

This command descends into myproject/ and forcefully sets the permissions of the directory itself, every folder nested inside it, and every single file inside it to exactly 755.

The Massive Danger of the Recursive Flag

While chmod -R is incredibly convenient, it is also considered a massive foot-gun in the sysadmin world. The fundamental problem lies in the fact that it blindly applies the exact same octal permission to both directories AND files indiscriminately.

Remember our golden rules from earlier? Directories must have 755 so they can be entered (the execute bit is required). Files, on the other hand, should ideally be 644 because they shouldn't be executable unless they are explicitly scripts.

If you run chmod -R 755 /path/to/folder, you have just unintentionally made every single JPEG image, HTML file, CSS stylesheet, and configuration file inside that folder executable by the operating system! While this might not break your application, it is remarkably sloppy system administration, violates the principle of least privilege, and can trigger aggressive security alerts in strict corporate auditing environments.

Worse, if you run chmod -R 777 /path/to/folder, you have just opened your entire project hierarchy to the world. And worst of all, if you accidentally run a recursive command on the system root directory (chmod -R 777 /)—perhaps due to a typo with a space—you will completely destroy your Linux operating system. Core system binaries, SSH configurations, and security files rely on strict, precise permission structures to function. The system will immediately begin failing and will almost certainly fail to boot the next time you restart it.

The Right Way: Combining Find and Chmod

To apply bulk permissions correctly and safely, professional system administrators combine the power of the find command with chmod. This powerful combination allows you to selectively filter and target only files, or only directories, and apply the correct, specific permission to each type independently.

Step 1: Set all DIRECTORIES to 755 safely

The following command uses find to search a specific path. The -type d flag instructs it to aggressively filter and only select Directories. When it finds a directory, it executes (-exec) the chmod 755 command exclusively on that directory. The {} acts as a placeholder for the found item, and the \; terminates the command.

find /var/www/html/myproject/ -type d -exec chmod 755 {} \;

Step 2: Set all FILES to 644 safely

Next, we utilize find with the -type f flag, which tells the system to only select standard Files. We then apply the secure chmod 644 permission to them.

find /var/www/html/myproject/ -type f -exec chmod 644 {} \;

Using this meticulous two-step method guarantees that your directories remain easily navigable while your sensitive files remain securely non-executable. It is the hallmark of a professional Linux administrator.

The Capital "X" Symbolic Trick

There is a lesser-known feature built directly into symbolic chmod that attempts to elegantly solve the recursive directory vs. file problem: the capital X permission flag.

When you use X (capital X) instead of x (lowercase x) during a recursive operation, chmod acts intelligently. It will selectively add the execute bit only if the target is a directory, OR if the target is a file that already has execute permissions previously set for at least one user class.

chmod -R a+X /path/to/folder

While incredibly useful for quick fixes, it relies on the existing state of the files being somewhat correct (i.e., you haven't already made all files executable accidentally). This is why the find command method detailed above is still the absolute most robust, predictable, and bulletproof way to secure a directory tree.

5. Advanced Topic: Fixing Web Server Permissions (www-data)

One of the most frequent reasons developers search for chmod tutorials is because their web application (like a fresh WordPress install, a Laravel project, or a custom Python Django script) is catastrophically failing to upload images, write to log files, or update cache directories.

As previously discussed, the rookie instinct is to aggressively chmod 777 the wp-content/uploads/ or storage/logs/ directories. But now you understand that this is a massive security risk that exposes your server to malicious payloads. So, how do you permanently fix web server permission errors securely?

The root cause of these frustrating errors is almost always ownership misalignment, not just permissions.

When you upload files via SFTP or clone a repository via SSH into your server, those files inherently belong to your personal user account (e.g., ubuntu, ec2-user, or developer). However, your web server software (Apache, Nginx, or LiteSpeed) runs as a completely different, isolated background service user. On Ubuntu and Debian systems, this background user is typically named www-data. On CentOS, RHEL, and Amazon Linux systems, it is often named apache or nginx.

If a directory is owned by ubuntu, and has the standard 755 permissions we recommend, the www-data user falls directly into the "Others" category. And what permission does the "Others" category have in 755? Just Read and Execute (4+1=5). They do not have Write (2) access! Therefore, when the web server attempts to process a user's image upload, the operating system blocks it, resulting in an error.

The Secure Solution: Group Ownership Strategy

Instead of giving the "Others" category global write access (making it a dangerous 777), you should logically change the group ownership of your web directory so that the web server group is granted the "Group" permissions.

Step 1: Set correct ownership using chown

Use the chown command to change the owner to yourself (so you can still easily edit files via SFTP or your IDE), and change the group to www-data (so the web server can interact with the files natively).

sudo chown -R your_user:www-data /var/www/html/your_site/

Step 2: Apply secure baseline permissions

Use our trusted find method to ensure all directories are strictly 755 and files are 644.

sudo find /var/www/html/your_site/ -type d -exec chmod 755 {} \;
sudo find /var/www/html/your_site/ -type f -exec chmod 644 {} \;

Step 3: Grant group write access strictly where required

Now, for the specific, isolated folders where the web server absolutely must write data (like an uploads folder, a framework cache folder, or a dedicated logs directory), you can elevate the "Group" write permissions. We change the directory to 775.

  • Owner (your_user): Read, Write, Execute (7)
  • Group (www-data): Read, Write, Execute (7) - The web server can now write!
  • Others (everyone else): Read, Execute (5) - Still securely locked out from writing.
sudo chmod -R 775 /var/www/html/your_site/wp-content/uploads/

With this architecture, your application is completely secure and fully functional. The web server can only write to the specific directories it explicitly needs to, your personal user account retains full overarching control, and unauthorized users or compromised scripts on the system have zero write access anywhere else.

6. Special Permissions: SUID, SGID, and the Sticky Bit

Beyond the standard Read, Write, and Execute bits we have covered extensively, Linux possesses three "special" permission modes. These are somewhat less common for day-to-day web development tasks but are absolutely vital for advanced system administration and security engineering. When calculating octal numbers with special permissions, a fourth digit is prepended to the front (e.g., chmod 4755).

SUID (Set User ID) - 4xxx or u+s

When the highly potent SUID bit is set on an executable binary file, any user who runs that file will execute it with the elevated privileges of the file's owner, rather than their own standard user account.

A classic, essential example of this in the Linux OS is the /usr/bin/passwd command. Normal, unprivileged users need to be able to change their own password. However, actually changing a password requires modifying the highly sensitive /etc/shadow file, which is strictly locked down and owned by the root user. Because the passwd binary has the SUID bit securely set, when a standard user runs it, the program momentarily elevates itself to full root privileges, makes the necessary change to the shadow file, and then safely drops back down to normal privileges.

Security Warning: Improperly assigning SUID to custom scripts or vulnerable binaries is one of the most common ways hackers achieve local privilege escalation to root.

chmod 4755 /path/to/binary
# or symbolically
chmod u+s /path/to/binary

SGID (Set Group ID) - 2xxx or g+s

SGID operates similarly to SUID on files (executing with the permissions of the file's assigned group), but its most profoundly useful application is on directories.

When the SGID bit is set on a directory, a special inheritance rule is activated. Any new file or folder created inside that directory will automatically inherit the group ownership of the parent directory, rather than defaulting to the primary group of the user who created it.

This is incredibly useful for collaborative enterprise shared folders. If a team of developers is working inside /var/www/shared_project/, setting the SGID bit ensures that every time Developer A creates a new file, Developer B (who is in the same group) can automatically edit it, without Developer A having to constantly run chown to fix ownership.

chmod 2775 /var/www/shared_project/
# or symbolically
chmod g+s /var/www/shared_project/

The Sticky Bit - 1xxx or +t

The sticky bit is a protective measure used almost exclusively on directories. When set, it mandates that users are prevented from deleting or renaming files within the directory unless they are the specific owner of the file (or the root user).

The most prominent, system-critical example of this is the /tmp directory in Linux. The /tmp folder must be world-writable (chmod 777) so that any application, script, or user on the system can create temporary scratch files. However, it would be chaotic and highly insecure if User A could just delete or maliciously overwrite User B's temporary files. The sticky bit solves this elegantly. Everyone can write to the directory, but you can only delete your own files.

chmod 1777 /tmp/
# or symbolically
chmod +t /tmp/

7. The Umask: How Default Permissions Are Decided

You might be wondering: when I create a brand new file using touch newfile.txt or a directory using mkdir newfolder, how does Linux decide what the initial permissions should be before I ever run chmod? The answer lies in the umask (user file-creation mode mask).

The umask acts as a filter that strips away permissions from a theoretical maximum. For directories, the starting maximum is 777. For files, the starting maximum is 666 (files are not executable by default).

A standard umask on many Linux systems is 022. When you create a directory, the system subtracts the umask from the maximum:
777 - 022 = 755 (The default directory permission!)

When you create a file, it subtracts the umask from the file maximum:
666 - 022 = 644 (The default file permission!)

Understanding the relationship between umask and chmod is the final piece of the puzzle in truly mastering Linux file creation and security lifecycles.

8. Troubleshooting Common Chmod Errors

Even armed with this extensive knowledge, you may occasionally run into frustrating errors when executing the chmod command in the heat of a deployment. Here are the most common ones and exactly how to resolve them.

"chmod: changing permissions of 'file': Operation not permitted"

This error occurs definitively when you attempt to change the permissions of a file that you do not own. In the strict Linux security model, only the specific owner of a file (or the superuser root) has the inherent authority to alter its permissions. Merely being a member of the file's group is not enough.

Solution: You must elevate your privileges using sudo. For example: run sudo chmod 755 filename. If you are on a restricted shared hosting environment without sudo access, you will need to contact your hosting provider's support team or use their specific web control panel tool to fix the underlying ownership.

"chmod: cannot access 'file': No such file or directory"

This is a simple but common pathing error. You are either misspelling the file name, dealing with hidden characters/spaces in the filename, or you are running the command in the wrong directory context.

Solution: Use the ls -la command to verify the file actually exists in your current working directory and to check its exact spelling. Alternatively, use absolute paths (e.g., chmod 755 /var/www/html/index.php) rather than relative paths to completely avoid shell ambiguity.

"Read-only file system"

You are attempting to change permissions on a drive that has been mounted by the kernel as read-only. This frequently happens on network drives (NFS/SMB), CD-ROM/ISO mounts, or, more alarmingly, if a hard drive encounters severe hardware errors and the Linux kernel forcefully remounts it as read-only to prevent catastrophic data corruption.

Solution: You cannot use chmod here. You must address the mount state first. You can attempt to remount the filesystem with read-write access (e.g., sudo mount -o remount,rw /mountpoint). If it fails due to hardware issues, you need to check your dmesg logs and likely repair the disk using fsck.

Conclusion

The chmod command is an undisputed cornerstone of Linux system administration and backend software engineering. Whether you are using concise numeric octals like 755 and 644 for rapid, predictable deployment, or surgical symbolic commands like u+x to quickly fix a broken deployment script, mastering file permissions is essential for maintaining a secure, robust, and highly functional server environment.

Remember the ultimate golden rule: Never use chmod 777 in a production environment. Always strive to follow the principle of least privilege—giving users, applications, and background services exactly the minimum permissions they need to execute their designated jobs, and absolutely nothing more. By intelligently combining chmod with chown and find, you can architect secure, scalable permissions for any web application, API, or collaborative enterprise project.

If you are ever in doubt about what a specific numerical code means, or fear making a mistake on a live server, don't guess. Head over to our Chmod Calculator to visually double-check your work, simulate the permissions, and generate the exact, secure command you need before pasting it into your terminal.