chmod Command in Linux: Complete Guide to Changing File Permissions and Parameters

chmod command in Linux and it perimeters

chmod command in Linux and it perimeters

chmod was the command that finally made Unix permissions click for me — not when I memorized that 755 means “rwxr-xr-x,” but when I understood why it means that, as three octal digits each built from the same three bits. Once that clicked, symbolic mode (u+x, go-w) stopped being a separate thing to memorize and became an obvious alternate notation for the same underlying bits. This guide covers both notations, the special bits that trip people up (setuid, setgid, sticky), and the real-world patterns I use for securing files and directories.

What Is the chmod Command?

chmod stands for “change mode.” It changes the permission bits of files and directories:

$ chmod --version
chmod (GNU coreutils) 9.4
Copyright (C) 2023 Free Software Foundation, Inc.

Basic Syntax

chmod [OPTION]... MODE[,MODE]... FILE...
chmod [OPTION]... OCTAL-MODE FILE...
chmod [OPTION]... --reference=RFILE FILE...

How Permission Bits Actually Work

Every file’s mode is stored as a set of bits in its inode. The permission-relevant bits break into three triads — owner, group, other — each with three flags: read (r, value 4), write (w, value 2), and execute (x, value 1). Adding those values together per triad gives you the familiar octal digits: 7 = rwx, 6 = rw-, 5 = r-x, 4 = r–, and so on down to 0 = —.

I tested this directly:

$ chmod 755 src.txt
$ ls -l src.txt
-rwxr-xr-x 2 root root 6 Jul 31 01:36 src.txt

7 (owner) = rwx, 5 (group) = r-x, 5 (other) = r-x — exactly matching the string rwxr-xr-x.

For a regular file, read means “can view content,” write means “can modify content,” and execute means “can run it as a program or script.”

For a directory, the same bits mean something different and this is the part that trips people up most: read means “can list the names inside it” (ls), write means “can create/delete/rename entries inside it” (note: this is about the directory’s own listing, not the permissions of files inside it), and execute means “can enter it and access things inside by name” (cd into it, or open a file inside it by path). A directory with r-- but no x lets you see filenames but not actually access or stat any of them — a subtlety that catches people by surprise the first time they hit it.

Symbolic Mode Notation

Alongside octal, chmod accepts symbolic expressions built from:

I tested a symbolic change directly:

$ chmod u+x src.txt
$ ls -l src.txt
-rwxr-xr-x 2 root root 6 Jul 31 01:36 src.txt

Symbolic mode’s real strength is that it can add or remove specific bits without needing to know or restate the current full modechmod g+w file adds group write regardless of whatever else was already set, while chmod 664 file requires you to specify the complete mode from scratch.

Special Permission Bits

Beyond the basic rwx triads, three additional bits matter a lot in real administration:

Full List of Parameters

OptionLong formDescription
-c--changesLike verbose, but report only when a change is actually made
-f--silent, --quietSuppress most error messages
-v--verboseOutput a diagnostic for every file processed
--no-preserve-rootDo not treat / specially (dangerous)
--preserve-rootRefuse to operate recursively on /
--reference=RFILEUse RFILE’s mode instead of specifying MODE
-R--recursiveChange files and directories recursively
--helpDisplay help and exit
--versionOutput version information and exit

Recursive traversal control (used with -R):

OptionDescription
-HIf argument is a symlink to a directory, traverse it
-LTraverse every symlink to a directory encountered
-PNever traverse symlinks (default)

Practical Examples with Output

Setting an exact octal mode:

$ chmod 644 report.txt
$ ls -l report.txt
-rw-r--r-- 1 root root 0 Jul 31 01:36 report.txt

Making a script executable:

$ echo '#!/bin/bash
echo hi' > script.sh
$ chmod +x script.sh
$ ls -l script.sh
-rwxr-xr-x 1 root root 18 Jul 31 01:36 script.sh
$ ./script.sh
hi

Removing all access for others:

$ chmod o-rwx private.txt

Setting different permissions for each category at once, symbolically:

$ chmod u=rwx,g=rx,o= script.sh
$ ls -l script.sh
-rwxr-x--- 1 root root 18 Jul 31 01:36 script.sh

Recursive change across a directory tree:

$ chmod -R 750 /srv/app/data

Setting the setgid bit on a shared team directory:

$ chmod g+s /srv/team_shared
$ ls -ld /srv/team_shared
drwxr-sr-x 2 root root 4096 Jul 31 01:36 /srv/team_shared

The lowercase s in the group execute position confirms setgid is active — new files created inside will inherit the directory’s group.

Setting the sticky bit on a shared, world-writable directory:

$ chmod +t /srv/shared_uploads
$ ls -ld /srv/shared_uploads
drwxrwxrwt 2 root root 4096 Jul 31 01:36 /srv/shared_uploads

Copying mode from a reference file:

$ chmod --reference=template.conf myfile.conf

Common Use Cases

Shell Scripting and Automation

Securing an SSH key immediately after generation, matching what ssh-keygen expects:

ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -N ""
chmod 600 "$HOME/.ssh/id_ed25519"
chmod 644 "$HOME/.ssh/id_ed25519.pub"

Locking down a secrets file as part of a deployment script:

#!/usr/bin/env bash
set -euo pipefail

SECRETS="/etc/myapp/secrets.env"
chmod 600 -- "$SECRETS"
chown appuser:appuser -- "$SECRETS"

Setting up a shared team directory with setgid inheritance:

mkdir -p /srv/team_shared
chown root:devteam /srv/team_shared
chmod 2775 /srv/team_shared

Real-World System Administration Workflows

Comparing chmod to Related Commands

Troubleshooting Common chmod Issues

“chmod: changing permissions: Operation not permitted”: you need to own the file (or be root) to change its mode — ownership, not group membership, is what grants the right to chmod in the first place.

Script won’t execute despite chmod +x: check the shebang line (#!/bin/bash etc.) is correct and the first line of the file, and confirm the filesystem the script lives on wasn’t mounted with the noexec option (common on /tmp in hardened setups).

SSH refuses a key even after chmod 600: check the parent directory permissions too — ~/.ssh itself needs to be 700; SSH validates the whole path, not just the key file.

Directory listing works but files inside can’t be opened: classic case of read permission without execute permission on the directory — you need x on a directory to traverse into it and access anything inside by name, not just r to list names.

setuid bit disappears after copying or editing the file: many tools (including cp without -p, and any editor that rewrites the file rather than modifying it in place) don’t preserve setuid/setgid bits by default, and the kernel actively strips setuid on write by some file managers as a security precaution — reapply explicitly if you genuinely need it.

Performance Considerations

chmod -R on very large trees has the same per-inode syscall overhead as chown -R — one operation per file. For huge trees, find /path -exec chmod MODE {} + is roughly equivalent in performance, batching arguments the same way -R already does internally, so there’s little to gain from switching between them beyond filtering flexibility (find lets you target only files, only directories, or match by name pattern).

Security Implications

Getting chmod wrong is one of the most common ways real systems get compromised. World-writable directories without a sticky bit let any user delete or replace another user’s files. Overly permissive private keys get silently rejected by SSH but might be accepted by less careful tools. Setuid root binaries are a classic privilege-escalation target — every setuid root file on a system is worth auditing periodically with find / -perm -4000 -type f 2>/dev/null. Never use 777 as a lazy fix for a permission error; it almost always means the ownership is wrong, not that every user on the system genuinely needs full access.

Best Practices

Compatibility Across Distributions

GNU chmod is identical in behavior across Debian/Ubuntu, RHEL/Fedora, Arch, and openSUSE. BusyBox chmod (Alpine, minimal containers) supports octal and basic symbolic modes plus -R but has a reduced option set, notably around --reference and full traversal control (-H/-L/-P) — check chmod --help in minimal images before relying on those.

Summary

chmod is really just an interface onto a small, elegant bit-field: three triads of read/write/execute, plus setuid, setgid, and sticky as extra flags layered on top. Once the octal-to-triad mapping and the directory-specific meaning of each bit are second nature, chmod stops being a command you look up and becomes a tool you reach for confidently — which matters, because getting permissions wrong (in either direction, too open or too closed) is one of the most common sources of both security incidents and confusing “permission denied” support tickets.

References

Exit mobile version