Chmod: read, write and execute in plain words

Almost every chmod explanation starts with a table of three letters and three audiences, and almost every one of them leaves the reader able to recite 644 without being able to predict what a command will do. The gap is not in the notation. The gap is that r, w and x authorise different operations depending on whether the thing they are attached to is a file or a directory, and the most surprising consequence of that, which is that deleting a file has nothing to do with the file's own permissions, is usually left out entirely.

The three letters are also a summary. On a Mac they sit on top of a second permission system whose vocabulary names seventeen separate rights, and when the two disagree the second one wins. Knowing where the summary stops is what turns chmod from guesswork into a decision.

What read actually authorises

On a regular file, r means the file can be opened for reading. That much matches intuition.

On a directory, r means something narrower than most people assume. It permits listing the names inside the directory, and nothing more. It does not permit looking up any of those names, which means it does not permit reading a file inside, checking its size, or finding out whether it is a file or another directory. A directory with read but no execute produces the odd result of a name list where every entry fails when touched.

The reason this split exists is visible in the other permission system on the Mac. The chmod manual page lists the rights that can appear in an access control list entry, and for directories it names list as "List entries" and search as "Look up files by name" as two separate rights. The POSIX letters collapse those two into r and x, and the awkwardness of r on a directory is the seam where that collapse shows.

This is why granting read access to a shared folder by handing out r alone does not work, and why the usual advice is to grant r-x together. It is not superstition. The two rights genuinely do different jobs, and only one of them is r.

Execute, and why a directory has it

On a regular file, x means the kernel will try to run the file as a program or hand it to an interpreter. The manual page's wording for the owner's execute bit makes the dual meaning explicit: "For files, allow execution by owner. For directories, allow the owner to search in the directory."

Search is the operation behind every path that resolves. Reaching /Users/name/Projects/notes.txt requires search permission on /, on Users, on name and on Projects, in that order, before the permissions on notes.txt are consulted at all. A single directory in that chain without x makes the file unreachable no matter how open the file itself is. This is the most common reason a mode that looks correct on the file still fails.

It also explains the one directory mode that is genuinely useful and looks wrong: execute without read. Such a directory cannot be listed, but a file inside it can be opened by anyone who already knows its exact name. That is a working, if blunt, way to publish something at an unguessable path.

Because the same letter means two different things, the symbolic mode has a capital X for the case where the distinction matters. The manual page defines it as "the execute/search bits if the file is a directory or any of the execute/search bits are set in the original (unmodified) mode", and adds that it is "only meaningful in conjunction with the op symbol +, and are ignored in all other cases". Applied down a tree, +X gives directories their search bit without marking every text file as a program.

Write is about the folder, not the file

This is the part that changes how people reason about permissions.

Deleting a file is not an operation on the file. It is an operation on the directory entry that names it, so the permission that governs it is w on the containing directory. A file with mode 444, readable by everyone and writable by nobody, can still be deleted by anyone who can write to the folder it sits in. Conversely, a file with mode 666 inside a directory the user cannot write to cannot be deleted by that user, only emptied.

The manual page states what w on a directory buys: "The w permission on directories will permit file creation, relocation, and copy into that directory. Files created within the directory itself will inherit its group ID." Creation, relocation and deletion are all directory operations.

The access control list vocabulary on the Mac is more honest about this than the three letters are. It defines delete as "Delete the item" and then immediately qualifies it: "Deletion may be granted by either this permission on an object or the delete_child right on the containing directory." Two independent routes to the same outcome, one on the file and one on the folder.

There is a documented escape from the folder rule, and it is the sticky bit. Setting 1000 on a directory makes it a restricted deletion directory, where a user can only remove entries they own even though the directory is writable by everyone. This is the mechanism that lets a shared scratch directory work without letting anyone clear out everyone else's files.

Who owner, group and other are on a single-user Mac

The three audiences are easy to name and hard to picture on a machine with one human on it.

The group database on a Mac carries the relevant entries with fixed numeric IDs. wheel is group 0, everyone is group 12, staff is group 20 and admin is group 80. Files created by a normal account in a home folder usually end up owned by that account with group staff, which is why ls -l shows staff so often.

That matters for the middle digit. On a machine with one account, group staff is close to being "any human who logs in", and admin is the group that can use administrator rights. Setting the group digit on a personal Mac rarely changes who can reach a file, and it is not the lever people reach for it expecting to be.

One detail is worth knowing before editing anything. The comment at the top of the group file states that "this file is consulted directly only when the system is running in single-user mode" and that "at other times this information is provided by Open Directory". Editing it in a text editor does not do what it looks like it does.

What each letter means, side by side

Letter On a regular file On a directory
r Open the file for reading List the names inside, nothing more
w Change the file's contents Create, rename, move and delete entries
x Run it as a program or script Look names up, so paths through it resolve
X (symbolic only) Only if some execute bit is already set Always applies
1000 sticky See the manual page for the historical meaning Only the owner of an entry may delete it

The two columns being different is the whole difficulty. A recursive change applies one mode to both kinds of thing, and one of the two columns is usually wrong afterwards.

The behaviour that catches people out

Symbolic mode has a rule that almost no tutorial mentions, and it changes what a short command does.

When the audience is left out, the file mode creation mask is consulted. The manual page spells this out for +: if no value is supplied for the audience, "each permission bit specified in perm, for which the corresponding bit in the file mode creation mask is clear, is set". The same qualification appears under - and under =.

So chmod +w file is not a shorthand for chmod a+w file. With a typical mask that withholds group and other write, it sets only the owner's write bit. Writing a+w explicitly is the way to mean all three audiences. This is a silent difference: nothing is reported, and the mode simply ends up narrower than intended.

The same gap exists on Linux, and the GNU implementation is worth comparing for a different reason: three of its options are absent on a Mac. --reference=ref_file copies another file's mode, --preserve-root refuses to recurse into /, and -c reports only the files that actually changed. Commands copied from a Linux guide using any of those will fail. The recursion default is reversed as well: the Mac manual page says -P, following no symbolic links, "is the default", while the GNU documentation says -H is the default when none of the three is given.

Where the three letters stop

Four things on a Mac override or bypass the mode bits, and none of them are fixed by chmod.

An access control list entry that denies a right wins over a mode bit that grants it. ls -le prints the list, numbered, and until that output is read the mode bits are only half the picture.

A file flag can freeze a file regardless of ownership. The user immutable flag, set with chflags uchg, prevents the owner from changing the file at all, and the chflags manual page points at ls -lO as the way to see existing flags.

Long listings hide one of these behind the other. A @ after the permission field means extended attributes are present, a + means extended security information such as an access control list, and the manual page for ls describes @ as taking the slot. A file with both shows only @, so an access control list can sit there invisibly. ls -l@ and ls -le have to be run separately.

The fourth is the system's own protection and the per application privacy controls, and it announces itself in the error text. The system error list defines error 13, EACCES, as "Permission denied" and error 1, EPERM, as "Operation not permitted". A refusal that says permission denied is about the mode bits. A refusal that says operation not permitted is about a flag or a system protection, and chmod will not move it.

Reading the state without three round trips

Knowing which of those four layers applies means running ls -l@, ls -le and ls -lO and comparing three outputs, because there is no single listing that shows all of it. Then the fix goes in, and the same three commands confirm it. The commands are short. The cost is the switching: a file picked in one window, inspected in another, changed in a third.

That is a layout problem rather than a command problem, and it is what a file manager with a built-in terminal is for, so a selection in the list and the command run against it are in the same place. What that looks like is set out in Features, and how it sits against the other options on the Mac is in Compared with other file managers.

What to change first

Before touching a mode, run ls -le on the file and read the error text of whatever failed: permission denied points at the mode bits, operation not permitted does not. When a whole tree needs changing, use +X rather than +x so directories get their search bit and text files stay inert. Keeping the listing and the shell in one window, which is the problem Atriens is built around, removes the part of this work that is only window switching.

Frequently asked questions

Why can someone delete a file they cannot write to?

Because deletion is a change to the directory that names the file, not to the file itself. Write permission on the containing folder is what authorises creating, renaming and removing entries, so a read-only file inside a writable folder can still be removed. The sticky bit on the folder is the documented way to restrict deletion to the owner of each entry.

Is `chmod +w file` the same as `chmod a+w file`?

No. When the audience is omitted, the file mode creation mask is consulted, and only the bits the mask leaves clear get set. With a typical mask that usually means the owner's write bit alone. Writing a+w is the way to mean owner, group and other, and nothing warns about the difference.

What is the point of read permission on a directory without execute?

Very little in practice, which is why the pairing r-x is the usual advice. Read alone permits listing the names inside and nothing else, so every attempt to open or inspect an entry fails. The access control list vocabulary on the Mac treats these as two separate rights, list and search, which is what the two POSIX letters are compressing.

Which group should the middle digit refer to on a personal Mac?

Usually staff, group 20, since that is what files created in a home folder normally carry. admin is group 80 and everyone is group 12. On a machine with a single account the group digit rarely changes who can reach a file, so it is not a useful lever for locking something down.

Why does chmod appear to succeed and change nothing?

Check for an access control list with ls -le and for file flags with ls -lO, because a deny entry or the user immutable flag will hold regardless of the mode. Note also that a long listing shows @ in place of +, so a file with extended attributes hides the marker that would have revealed the access control list.

Back to all posts