Recursive chmod and Why 755 Across a Source Tree Is Wrong
chmod -R applies the same mode to every file and every directory below a path. Because directories need the execute bit and ordinary files do not, a single recursive mode is wrong for one of the two, whichever value you pick.
At a glance
- Flag
- -R, or --recursive
- The core problem
- Directories need execute to be traversable, regular files should not have it
- chmod -R 755
- Directories correct, every source file and image marked executable
- chmod -R 644
- Files correct, every directory unenterable, including for the owner
- The find pattern
- find PATH -type d -exec chmod 755 {} + then find PATH -type f -exec chmod 644 {} +
- The capital X pattern
- chmod -R a=rX,u+w PATH sets execute on directories only, plus files that already had it
- Symbolic links
- chmod does not follow symbolic links found during recursion, and cannot change a link's own mode
In detail
The problem with chmod -R is that a directory and a regular file want different things from the same nine bits. Directories need execute for traversal. Data files should not have it. One recursive mode cannot satisfy both, so chmod -R 755 leaves every stylesheet and JPEG marked as a program, and chmod -R 644 leaves a tree that nobody can enter, including the person who ran it.
The second of those is the more alarming and the easier to fix, because the failure is immediate and total. The first is worse in practice: it looks like it worked, it shows up as a mode change on every file in version control, and it defeats any tooling or audit that treats an unexpected executable as a signal.
There are two clean patterns. Two find passes, one for directories and one for files, is explicit and reads well in a script. The capital X form does it in one command, because X sets execute only on directories and on files that already had an execute bit somewhere, which preserves genuine scripts while leaving data alone.
Symbolic links are handled sensibly and quietly. chmod cannot change the mode of a symbolic link itself, since the mode is not used, and it does not follow links encountered during a recursive walk. That means a recursive chmod through a tree containing a link to somewhere else will not wander into that other tree, which is the behaviour you want and the opposite of what many people assume.
Before running anything recursive, look at what it will touch. A dry run with find and no -exec prints the list, and the calculator's recursive checkbox shows the exact command it would produce, including the -R flag and the shell quoting for a path with spaces in it. Reading the command before running it is the whole safety procedure.
Examples
$ chmod -R 755 ./src
-rwxr-xr-x index.ts # marked executable, it is not a program
-rwxr-xr-x logo.png # so is this
$ chmod -R 644 ./src
drw-r--r-- src/ # nobody can enter it now
$ cd src
bash: cd: src: Permission deniedfind ./src -type d -exec chmod 755 {} +
find ./src -type f -exec chmod 644 {} +
# then restore the execute bit only where it belongs
chmod 755 ./src/bin/build.shchmod -R a=rX,u+w ./src
# a=rX everyone reads; execute only on directories and
# on files that already had an execute bit
# u+w the owner can still writeThings that catch people out
- chmod -R 755 on a project marks every file executable and shows up as a mode change on every file in version control, which buries any real change in the diff.
- chmod -R 644 removes traversal from every directory in the tree, and the very next command you run will fail. Fixing it needs a directory pass, not another recursive file mode.
- A three digit recursive mode preserves setgid on directories under GNU chmod, so a tree relying on group inheritance may survive by accident and then break on a different system.
- Recursive changes on a large tree are not atomic. If you interrupt one halfway you get a tree in two different states, which is much harder to reason about than either endpoint.
Try it: Chmod Calculator
Tick the nine permission boxes, or type an octal or symbolic value, and get the three digit and four digit octal, the ls -l rendering and the exact chmod command back.
Chmod Calculator
LOCAL · Browser-OnlyCalculate Unix file permissions with an interactive chmod builder
Permission Matrix
| Entity | Read (4) | Write (2) | Execute (1) | Octal | Symbolic |
|---|---|---|---|---|---|
| Owner (u) | 7 | rwx | |||
| Group (g) | 5 | r-x | |||
| Others (o) | 5 | r-x |
Special Bits
Advanced permission flags for executables and directories
Generated Permissions
755rwxr-xr-x-rwxr-xr-xchmod 755 filenamechmod u=rwx,g=rx,o=rx filenamePermission Breakdown
Owner (u)
7rwx- - Read files / list directory contents
- - Write / modify / delete
- - Execute / traverse directory
Group (g)
5r-x- - Read files / list directory contents
- - Execute / traverse directory
Others (o)
5r-x- - Read files / list directory contents
- - Execute / traverse directory
Common Permissions Reference
| Octal | Symbolic | Meaning |
|---|---|---|
777 | rwxrwxrwx | Full access for everyone |
755 | rwxr-xr-x | Owner full, others read and execute |
750 | rwxr-x--- | Owner full, group read and execute |
700 | rwx------ | Owner full access only |
666 | rw-rw-rw- | Read and write for everyone |
644 | rw-r--r-- | Owner read/write, others read only |
600 | rw------- | Owner read/write only |
555 | r-xr-xr-x | Read and execute for everyone |
444 | r--r--r-- | Read only for everyone |
400 | r-------- | Owner read only |
Related File permissions
All file permissions →chmod 755: The Standard Mode for Directories and Programs
755 gives the owner full control and everyone else read and execute. Why it is right for directories and executables and wrong for ordinary data files.
chmod 644: The Default File Mode and When to Change It
644 gives the owner read and write and everyone else read only. Why it is the default for files under a 022 umask, and the cases where it is wrong.
Symbolic chmod Notation: u, g, o, a With Plus, Minus and Equals
Symbolic mode changes one class at a time instead of setting all nine bits. How plus, minus and equals differ, and what the capital X form is for.
The Execute Bit on a Directory Means Traverse, Not Run
On a directory, execute grants the right to resolve names through it and read grants the right to list them. Why a directory at 644 cannot be entered.
chmod +x: Making a File Executable and the umask Catch
chmod +x adds the execute bit, but without a class it is masked by the umask. Why scripts also need read, and how to record the bit in version control.
How to Read an ls -l Permission String Such as rwxr-xr-x
The ten characters at the start of an ls -l line decode to a file type and three permission classes. What s, S, t, T and a trailing plus mean.
Tools for this
- Chmod Calculator Free online chmod calculator - calculate Unix file permissions with an interactive chmod builder