DEV Community

Cover image for Understanding chmod Without Memorizing Numbers
Asep Sayyad
Asep Sayyad

Posted on • Originally published at asepsayyad007.Medium

Understanding chmod Without Memorizing Numbers

How Linux file permissions actually work under the hood, why symbolic mode is your best friend, and how to stop blindly typing chmod 777.

Every Linux engineer has been there.

You write a brand-new bash script, try to run it from your terminal, and hit an immediate roadblock:

$ ./backup.sh
bash: ./backup.sh: Permission denied
Enter fullscreen mode Exit fullscreen mode

You open your search engine or ask a chat assistant for help. Within seconds, you find an answer that tells you to run:

chmod 777 backup.sh
Enter fullscreen mode Exit fullscreen mode

You run the command, hit enter, and the script runs. Problem solved, right?

Not quite. In fact, you just opened the digital front door of that file to every single user and background service on the entire operating system.

When I started managing Linux servers years ago, permissions felt like a strange puzzle of three-digit math problems. People kept throwing numbers around: 755 for scripts, 644 for web pages, 600 for SSH keys, and 777 whenever something broke and nobody knew why.

I memorized those numbers like cheat codes in a video game. But whenever I had to handle a real permission problem, like giving a development team write access to a shared log folder without letting them delete each other's files, memorized numbers fell apart.

Here is the secret: you do not need to do binary math or memorize three-digit codes to master Linux permissions.

Linux has a built-in, human-readable permission syntax called symbolic mode. Once you understand how Linux looks at files, who owns them, and what actions each permission controls, chmod becomes one of the most intuitive tools in your terminal.

Let's break down how it all works step by step.


1. What chmod Actually Does

The name chmod stands for change mode.

In Unix and Linux systems, every single file and directory has a "mode". That mode determines who is allowed to read it, write to it, or run it.

When you run chmod, you are simply updating those access bits inside the Linux filesystem inode.

To see the current mode of your files, open any terminal and run ls -l:

$ ls -l
total 16
-rw-r--r-- 1 asep asep  420 Aug 17 21:00 app.config
-rwxr-xr-x 1 asep asep 1280 Aug 17 21:05 deploy.sh
drwxr-xr-x 2 asep asep 4096 Aug 17 21:10 logs
Enter fullscreen mode Exit fullscreen mode

Look at that strange 10-character string on the far left, like -rwxr-xr-x. That single string tells you everything you need to know about the file.

Let's dissect it.


2. Breaking Down the 10-Character Permission String

The 10 characters at the start of an ls -l line look intimidating at first. But when you split them into four distinct parts, they make total sense.

Here is how the string -rwxr-xr-x is organized:

  • Position 1 (File Type): -
  • Positions 2, 3, 4 (User / Owner): rwx
  • Positions 5, 6, 7 (Group): r-x
  • Positions 8, 9, 10 (Others / World): r-x

Let's inspect each of these four parts.

The First Character: File Type

The very first character tells you what kind of item you are looking at:

  • - = A regular file (a text document, an image, a binary program, or a shell script).
  • d = A directory (a folder).
  • l = A symbolic link (a shortcut pointing to another file or path).
  • c = A character device file (like a terminal tty or /dev/null).
  • b = A block device file (like a hard disk partition under /dev/sda1).
  • s = A local Unix domain socket.
  • p = A named pipe (FIFO).

Most of the time, you will see - for files and d for directories.

The Three Permission Roles (The "Who")

The remaining 9 characters are divided into three equal triplets of 3 characters each. They answer the question: Who gets access?

  • User (u): The individual user account that owns the file. This is usually the person or service account that created it.
  • Group (g): The group of users assigned to the file. Anyone who belongs to this group shares these permissions.
  • Others (o): Everyone else. Any user account on the machine that is neither the owner nor a member of the file's group.

The Three Basic Permissions (The "What")

Inside each triplet, you will see three letters, or a dash (-) if that permission is turned off:

  • r = Read permission. Allows reading the file or listing directory contents.
  • w = Write permission. Allows modifying the file or creating/deleting items in a directory.
  • x = Execute permission. Allows running the file as a program or entering a directory.
  • - = Permission denied. That specific action is turned off.

Now look back at -rwxr-xr-x:

  • The owner (u) has rwx: can read, write, and execute.
  • The group (g) has r-x: can read and execute, but cannot write or modify.
  • Others (o) have r-x: can read and execute, but cannot write or modify.

No math required. You can read it directly like a sentence.


3. The Three Questions Method: Who, Action, What

Instead of calculating numbers in your head, symbolic chmod uses a simple three-part formula:

chmod [WHO][ACTION][WHAT] filename
Enter fullscreen mode Exit fullscreen mode

You only need to answer three simple questions:

  1. Who are you changing permissions for? (u, g, o, or a for all)
  2. What action do you want to take? (+ to add, - to remove, = to set exactly)
  3. What permission are you changing? (r, w, or x)

Let's look at each piece.

1. The Who Options

  • u = User (the owner)
  • g = Group
  • o = Others
  • a = All three roles combined (u + g + o)

If you leave out the "Who" entirely and just write +x, Linux defaults to applying the change based on your system umask, which usually acts like a+x.

2. The Action Options

  • + = Add a permission without touching the existing permissions.
  • - = Remove a permission without touching the existing permissions.
  • = = Set the exact permissions, clearing out anything else for that role.

3. The What Options

  • r = Read
  • w = Write
  • x = Execute

Let's see this in action with everyday examples.


4. Real-World Symbolic chmod in Action

Let's walk through common terminal situations where symbolic mode makes life much easier than guessing numbers.

Example 1: Making a Script Executable Safely

You just wrote a new deployment script deploy.sh. By default, newly created files do not have execute permissions.

You want to make it executable for yourself (the owner), without changing anything else:

chmod u+x deploy.sh
Enter fullscreen mode Exit fullscreen mode

Before: -rw-r--r--
After: -rwxr--r--

If you want everyone on the machine to be able to execute it:

chmod a+x deploy.sh
Enter fullscreen mode Exit fullscreen mode

or simply:

chmod +x deploy.sh
Enter fullscreen mode Exit fullscreen mode

Before: -rw-r--r--
After: -rwxr-xr-x

Notice how clean this is. You did not have to remember what the other permission bits were. You did not risk accidentally removing read or write access. You simply added the execute bit.

Example 2: Locking Down a Private File

You have a sensitive file called database.env that contains database credentials. You want to make sure nobody else on the server can read it:

chmod go-rwx database.env
Enter fullscreen mode Exit fullscreen mode

This tells Linux: for Group (g) and Others (o), remove (-) read, write, and execute (rwx).

Before: -rw-r--r--
After: -rw-------

Now, only your user account can open and read that file.

Example 3: Giving Your Team Write Access to a Log File

You share a server with a small team. You created a file called service.log and want anyone in your shared group to be able to write log entries to it, while keeping strangers read-only:

chmod g+w service.log
Enter fullscreen mode Exit fullscreen mode

Before: -rw-r--r--
After: -rw-rw-r--

You did not have to recalculate the octal sum for user, group, and other. You just turned on group write.

Example 4: Setting Exact Permissions with the Equals Sign (=)

Sometimes you want to wipe whatever permissions currently exist and set an exact rule. Use the = operator:

chmod u=rw,go=r config.yaml
Enter fullscreen mode Exit fullscreen mode

This sets:

  • User (u) to exact Read and Write (rw)
  • Group (g) and Others (o) to exact Read-only (r)

Even if the file was previously 777 or completely locked down, this one command resets it to a clean state.


5. Files vs. Directories: The Huge Difference Nobody Explains

One of the biggest sources of confusion in Linux permissions is that r, w, and x mean something completely different on a directory than on a regular file.

If you treat a folder the exact same way you treat a text file, you will quickly lock yourself out or create strange bugs.

Let's compare them directly.

1. Read (r)

  • On a File: Allows opening and reading the file contents (using tools like cat, less, or grep).
  • On a Directory: Allows listing the names of files inside the directory (using ls).

2. Write (w)

  • On a File: Allows modifying or editing the contents of the file.
  • On a Directory: Allows creating, deleting, and renaming files inside that directory.

Crucial Rule: In Linux, deleting a file does not depend on the permissions of the file itself! It depends entirely on the write (w) permission of the parent directory. If a user has write permission on the folder, they can delete any file inside it, even if the file is marked read-only.

3. Execute (x)

  • On a File: Allows running the file as a compiled program or executable script.
  • On a Directory: Allows entering and traversing the directory (using cd) and accessing file metadata or reading files inside if you know their names.

The Classic Directory Trap

What happens if a directory has Read permission (r), but NO Execute permission (x)?

Let's test this in a real terminal:

$ mkdir testdir
$ touch testdir/secret.txt
$ chmod u=r testdir
$ ls -l testdir
ls: cannot access 'testdir/secret.txt': Permission denied
total 0
-????????? ? ? ? ?            ? secret.txt
Enter fullscreen mode Exit fullscreen mode

Look at that output. Because you have r, ls can see that a file named secret.txt exists. But because you lack x, Linux cannot enter the directory to check file sizes, timestamps, or ownership. Everything shows up as question marks!

And if you try to cd into it:

$ cd testdir
bash: cd: testdir: Permission denied
Enter fullscreen mode Exit fullscreen mode

For a directory to be usable in Linux, it must always have the execute (x) permission.


6. The Capital 'X' Trick (The Sysadmin Secret)

Here is a common scenario that trips up almost every Linux administrator.

You have a directory tree with hundreds of folders, subfolders, and text files. Someone messed up permissions across the entire project, and you want to fix it recursively.

If you run:

chmod -R +x myproject/
Enter fullscreen mode Exit fullscreen mode

Every single directory becomes accessible, which is great. But now, every single .txt, .jpg, .json, and .md file also becomes marked as an executable program! That is messy and wrong.

If you run:

chmod -R -x myproject/
Enter fullscreen mode Exit fullscreen mode

You fix the files, but you just locked yourself out of all the subdirectories because directories lost their x bit!

The Solution: Capital X

Linux symbolic mode has a special operator designed specifically for this problem: uppercase X.

Uppercase X means: Apply execute permission ONLY if the target is a directory, or if it already has execute set for someone.

Look at how you can fix an entire directory tree in one clean command:

chmod -R u=rwX,go=rX myproject/
Enter fullscreen mode Exit fullscreen mode

What does this single command do?

  1. Every directory gets rwx for user and r-x for group and others (fully traversable).
  2. Every regular file gets rw- for user and r-- for group and others (read-only for group/others, non-executable).

No scripts, no complicated find commands, no headache. Capital X handles directories and files properly in one shot.


7. How the Numbers Work (When You Must Read Them)

Even if you use symbolic mode for everyday work, you will still run into three-digit octal numbers in configuration files, Dockerfiles, Ansible playbooks, and Terraform templates.

You do not need to memorize these numbers. You can calculate them in one second once you know where they come from: basic binary bits.

In the Linux kernel, permissions are stored as three binary bits:

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

To find the number for any role, just add the values together:

  • rwx = 4 + 2 + 1 = 7 (Full permissions)
  • rw- = 4 + 2 + 0 = 6 (Read and Write)
  • r-x = 4 + 0 + 1 = 5 (Read and Execute)
  • r-- = 4 + 0 + 0 = 4 (Read only)
  • -w- = 0 + 2 + 0 = 2 (Write only - rare)
  • --x = 0 + 0 + 1 = 1 (Execute only)
  • --- = 0 + 0 + 0 = 0 (No access at all)

When you see a three-digit code like 755, each digit represents one of the three roles:

  • First digit (7): User (rwx = 4 + 2 + 1)
  • Second digit (5): Group (r-x = 4 + 0 + 1)
  • Third digit (5): Others (r-x = 4 + 0 + 1)

Let's review the five standard numbers you will see across all Linux systems:

  • 600 (rw-------): Only the owner can read and write. Used for private SSH keys (~/.ssh/id_ed25519), AWS credentials, and sensitive config files.
  • 644 (rw-r--r--): The owner can read and write; everyone else can only read. Standard for HTML files, documents, stylesheets, and general configuration files.
  • 700 (rwx------): Only the owner can read, write, and enter. Standard for private user directories like ~/.ssh or user home folders.
  • 755 (rwxr-xr-x): The owner can read, write, and execute; everyone else can read and execute. Standard for system binaries in /usr/bin, scripts, and public web directories.
  • 777 (rwxrwxrwx): Everyone can read, write, execute, modify, and delete. The danger zone.

8. Why chmod 777 is a Production Trap

When people run into a permission error on a server, the most common quick fix is typing sudo chmod 777 -R /path/to/folder.

It seems harmless on your personal laptop, but in a production or multi-user environment, 777 is a major security hazard.

Here is what 777 actually means:

  • Any local user, background service, or compromised container on the system can modify your files.
  • A web server process (like www-data or nginx) that gets exploited can overwrite your scripts, inject malicious code, or drop web shells directly into your application directory.
  • Tools like SSH and OpenSSL will actively refuse to work if key files have loose permissions. If you run chmod 777 ~/.ssh/id_rsa, SSH will reject the key and refuse to connect:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/home/asep/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Enter fullscreen mode Exit fullscreen mode

The Right Way: Fix Ownership, Not Permissions

When an application cannot write to a directory, the issue is almost never that permissions are too tight. The issue is usually ownership.

Instead of making the folder world-writable with 777, change the owner to the user that runs the application using chown:

# Bad practice:
sudo chmod -R 777 /var/www/my-app/uploads

# Good practice:
sudo chown -R www-data:www-data /var/www/my-app/uploads
sudo chmod -R 750 /var/www/my-app/uploads
Enter fullscreen mode Exit fullscreen mode

Now, only the web server user (www-data) can write to the upload directory. Other users on the machine cannot snoop or modify its contents.


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

Beyond basic rwx, Linux has three special permission bits that solve specific administrative challenges.

You can spot them when you see letters like s, S, t, or T in the ls -l output.

1. SUID (Set User ID)

When SUID is placed on an executable file, any user who runs that file temporarily gains the permissions of the file's owner, rather than their own user account.

A classic example is /usr/bin/passwd:

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Aug 17 12:00 /usr/bin/passwd
Enter fullscreen mode Exit fullscreen mode

Notice the s where the user execute x would normally be.

When a regular user wants to change their password, the passwd tool needs to write the new hashed password into /etc/shadow, which is owned by root. Thanks to SUID, the tool runs with root authority just long enough to update the password securely.

To set SUID symbolically:

chmod u+s /path/to/binary
Enter fullscreen mode Exit fullscreen mode

To remove it:

chmod u-s /path/to/binary
Enter fullscreen mode Exit fullscreen mode

2. SGID (Set Group ID)

SGID works in two different ways:

  • On an executable file: The program runs with the permissions of the file's group.
  • On a directory: Any new file or subfolder created inside automatically inherits the group owner of the parent directory, instead of the primary group of the person who created it.

This is the standard solution for shared team folders.

Imagine you have a shared directory /opt/dev-team for developers:

sudo chown -R :developers /opt/dev-team
sudo chmod g+s /opt/dev-team
Enter fullscreen mode Exit fullscreen mode

Now, whenever developer Alice creates a new file inside /opt/dev-team, the file is automatically assigned to the developers group. Bob and Charlie can immediately collaborate on it without manual permission fixes.

To set SGID symbolically on a directory:

chmod g+s /path/to/folder
Enter fullscreen mode Exit fullscreen mode

3. The Sticky Bit

When the sticky bit is set on a directory, only the owner of a file (or root) can delete or rename that file, even if the directory itself gives write access to everyone.

The most famous example is the /tmp directory:

$ ls -ld /tmp
drwxrwxrwt 22 root root 4096 Aug 17 21:00 /tmp
Enter fullscreen mode Exit fullscreen mode

Notice the t at the very end.

Every program on the machine needs to write temporary files to /tmp. But without the sticky bit, any rogue user or process could delete another user's temp files. The sticky bit ensures everyone can create files, but nobody can delete anyone else's data.

To set the sticky bit symbolically:

chmod +t /path/to/shared-folder
Enter fullscreen mode Exit fullscreen mode

10. How umask Decides Default Permissions

Have you ever wondered why every new file you create with touch gets -rw-r--r-- (644), while every new folder gets drwxr-xr-x (755)?

The answer is your shell's umask (user file-creation mode mask).

Linux does not assign random permissions. It starts with maximum default base permissions:

  • Maximum base mode for files: 666 (rw-rw-rw- - no automatic execute for safety)
  • Maximum base mode for directories: 777 (rwxrwxrwx)

Then, it masks out (subtracts) the values defined in your umask.

To check your current umask, type:

$ umask
0022
Enter fullscreen mode Exit fullscreen mode

Here is the math Linux does behind the scenes with a standard umask of 0022:

  • New File: 666 - 022 = 644 (rw-r--r--)
  • New Directory: 777 - 022 = 755 (drwxr-xr-x)

If you want a more secure environment where new files are private to you and cannot be read by anyone else, you can set a stricter umask in your ~/.bashrc:

umask 0077
Enter fullscreen mode Exit fullscreen mode

With 0077:

  • New files will be created as 600 (rw-------).
  • New folders will be created as 700 (rwx------).

11. Practical Cheat Sheet: Symbolic vs. Numeric

Here is a quick reference guide of the most common permission tasks you will encounter on Linux servers.

  • Make a script executable for everyone:

    • Symbolic: chmod +x run.sh
    • Numeric: chmod 755 run.sh
  • Make a script executable for owner only:

    • Symbolic: chmod u+x run.sh
    • Numeric: chmod 700 run.sh
  • Lock down a private SSH key file:

    • Symbolic: chmod go-rwx ~/.ssh/id_rsa
    • Numeric: chmod 600 ~/.ssh/id_rsa
  • Secure an entire .ssh directory:

    • Symbolic: chmod u=rwx,go-rwx ~/.ssh
    • Numeric: chmod 700 ~/.ssh
  • Standard public web file (HTML, CSS, JS):

    • Symbolic: chmod u=rw,go=r index.html
    • Numeric: chmod 644 index.html
  • Make group members able to edit a file:

    • Symbolic: chmod g+w app.log
  • Fix an entire project tree safely (dirs traversable, files non-executable):

    • Symbolic: chmod -R u=rwX,go=rX /path/to/project
  • Set up a shared team folder with group inheritance:

    • Command: sudo chmod g+s /path/to/shared

12. Interesting Fact

The 9-bit permission model used by chmod was introduced by Ken Thompson and Dennis Ritchie in Unix Version 1 back in 1971.

In earlier operating systems like Multics, access control lists were complex, dynamic data structures that took up considerable memory. Thompson and Ritchie needed something so compact that the entire file mode (file type, permissions, SUID bit, and allocation flags) could fit inside a single 16-bit integer word on their PDP-11 minicomputer.

That elegant 16-bit decision made in 1971 was so efficient that it remains the core permission foundation running on billions of Linux servers, Android phones, cloud instances, and supercomputers today.


Key Takeaways

Managing Linux permissions does not require memorizing octal numbers or doing binary math under pressure.

  1. Think in Roles: User (u), Group (g), Others (o), and All (a).
  2. Use Symbolic Actions: Add (+), Remove (-), or Set (=).
  3. Remember Directory Rules: Directories always need the Execute (x) bit so you can enter and traverse them.
  4. Use Capital X for Recursive Fixes: chmod -R u=rwX,go=rX fixes entire directory trees safely without breaking file permissions.
  5. Never Use 777 as a Shortcut: Fix folder ownership with chown instead of blowing open permissions.

Once you start using symbolic notation in your daily workflow, you will make fewer mistakes, keep your servers secure, and never have to stop and count octal numbers again.


What is Your Go-To chmod Command?

Do you prefer using symbolic notation like chmod +x or do you stick with classic numeric codes like 755? Have you ever run into a strange permission bug that took hours to debug? Let me know in the comments below!


About the Author

Asep Sayyad is a Linux and DevOps engineer passionate about Linux administration, automation, cloud technologies, containers, and open-source software. He enjoys solving real-world infrastructure challenges and sharing practical knowledge through in-depth technical articles, tutorials, and hands-on guides.

His goal is to help aspiring and experienced engineers build stronger Linux and DevOps skills with content focused on real production scenarios rather than theory alone.

Connect with Me

Portfolio: https://asepsayyad007.in
GitHub: https://github.com/asepsayyad007
LinkedIn: https://www.linkedin.com/in/asepsayyad
Medium: https://asepsayyad007.medium.com

Enjoyed this article?

If you found this guide helpful, consider:

  • Starring my open-source projects on GitHub.
  • Sharing this article with fellow Linux and DevOps engineers.

You can also follow me for more practical content on Linux, DevOps, Cloud, Containers, Automation, and Open Source. Thanks for reading, and enjoy your learning!

© 2026 Asep Sayyad

Top comments (0)