Matheion

MA-CLI1 · Module 1.5

File permissions

Topics: chmod · rwx · Octal modes

Overview

Module 1.5 — File permissions

Who may read, change, or run each file? Decode ls -l, set modes with symbolic or octal chmod, and design intents such as 600, 644, 755, and 751.

By the end you should be able to: read owner/group/other triples; explain directory x as traverse; choose a mode from intent, then verify with ls -l.

Scroll Core ideas → worked examples → Quiz. Practice only on files you created. Plan on roughly 50–60 minutes.

Concepts

Core ideas — who may read, write, or execute

Picture the tidewatch project folder on a computer that several people share. Sam keeps a half-finished field report there, a teammate keeps a script that downloads gauge readings, and the whole team reads a public summary. Not all of these files should be open to everyone in the same way. The system needs a small, precise vocabulary for saying "this person may look, that person may change, nobody else may touch." That vocabulary is permissions, and it is short enough that you can learn the whole of it in one sitting.

Take this slowly. There are only two ideas to hold at once: who is asking, and what they want to do.


The three classes: owner, group, other

Every file and directory records an owner (one user account), a group (a named set of accounts), and then implicitly everybody else. Permissions are written separately for each of these three classes:

| Class | Short name | Who it covers | |-------|-----------|---------------| | Owner | u (user) | The one account that owns the item, usually whoever created it | | Group | g | Accounts that belong to the item's group | | Other | o | Every remaining account on the system |

When you try to open a file, the system checks which class you fall into and applies only that class's permissions. It does not add them up. If you are the owner, the owner's permissions apply to you, even if the group's permissions would have been more generous. That detail surprises people, so it is worth reading twice: the checks go owner first, then group, then other, and the first match decides.


The three actions: read, write, execute

For each class there are three switches, each either on or off:

  • r (read) — look at something.
  • w (write) — change something.
  • x (execute) — run something, or pass through something.

The words are simple, but their meaning shifts depending on whether the item is a file or a directory. This table is worth keeping nearby:

| Letter | On a file | On a directory | |--------|---------------|--------------------| | r | Read the contents (cat, less) | List the names inside (ls) | | w | Change the contents (edit, overwrite, append) | Create, delete, and rename entries inside | | x | Run it as a program or script | Traverse: pass through it to reach what is inside (cd, or naming a path that goes through it) |

Notice how the file column is intuitive and the directory column is not. A directory is really a little list of names, so "read" means "see the list," "write" means "edit the list," and "execute" means "use the list to get somewhere."


Execute on a directory means traverse

The x bit on a directory deserves its own section, because it is the most common source of confusion in this whole module.

Imagine the directory tidewatch/data/ as a corridor with a door at the near end. The r bit lets you read the sign on the door that lists the rooms behind it. The x bit is the key to the door itself. Without the key you cannot walk down the corridor, whether or not you were allowed to read the sign.

Here is what each combination does for a directory you do not own:

| Mode on directory | ls dir (list names) | cd dir (enter) | cat dir/file (reach a known name) | |-------------------|-----------------------|------------------|-------------------------------------| | r-x | works | works | works if the file itself is readable | | r-- | lists names, but details fail | fails | fails | | --x | fails | works | works if you already know the exact name | | --- | fails | fails | fails |

The --x row is the odd one: a directory you can walk through but not look into, like a hallway with no signs. It is rare in practice, but understanding it proves you understand x.

The rw- combination, by the way, is almost never what you want on a directory. Without x you cannot reach anything inside, so the w bit is useless. In practice, directories you want to use get x whenever they get r.

There is one more consequence worth stating. To create, delete, or rename an entry inside a directory you need both w and x on that directory. Notice that deleting a file depends on the directory's w bit, not on the file's own. A file marked read-only can still be deleted by someone who has write access to the folder holding it.


Reading permissions with ls -l

The long listing is the window into all of this. Here is a line from the tidewatch project:

-rwxr-x--x  1 sam  crew  412 Oct 14 09:30 sync_readings.sh

Look at the very first column, ten characters wide: -rwxr-x--x. Split it into four parts:

-     rwx     r-x     --x
|     |       |       |
type  owner   group   other
  • The first character is the file type. - means a regular file, d means a directory, and l means a symbolic link.
  • The next three (rwx) are the owner's permissions: read, write, execute all on.
  • The middle three (r-x) are the group's: read on, write off, execute on.
  • The last three (--x) are everyone else's: only execute is on.

A dash in any slot simply means "that switch is off." Every triple always comes in the order r, w, x, so you can read them by position. The third character of a triple is x or -; the first is always r or -.

Here is a directory for comparison:

drwxr-xr-x  5 sam  crew  160 Oct 14 09:00 tidewatch

The leading d tells you it is a directory, then rwx r-x r-x means the owner has full access and everyone else may list and enter it but not change its contents.

The remaining columns tell you the link count, the owner (sam), the group (crew), the size in bytes, the last-modified time, and the name. Owner and group show whose permissions apply to whom.


Changing permissions — symbolic form

The command that changes permissions is chmod (change mode). It has two dialects. The symbolic one reads almost like a sentence: who, then an operator, then what.

chmod u+x sync_readings.sh

Read it aloud: "for the user, add execute." The pieces:

| Piece | Meaning | |-------|---------| | u | the owner (user) | | g | the group | | o | others | | a | all three at once | | + | add these permissions, leaving the rest alone | | - | remove these permissions, leaving the rest alone | | = | set exactly these, clearing everything else for that class |

You can combine classes (go), combine letters (rx), and chain several instructions with commas and no spaces:

chmod u+rwx,g+rx,o+x sync_readings.sh   # owner rwx, group r-x, other --x (if starting from nothing)
chmod go-w private_draft.txt             # group and others lose write; owner untouched
chmod o= private_draft.txt               # others get nothing at all
chmod u=rw,go=r field_log.txt            # owner rw-, group and others r--

The big advantage of symbolic form is that + and - change only what you name. If a file is rwxr-xr-x and you run chmod go-w, the owner's bits stay exactly as they were. That makes symbolic form the safer choice when you want to make a small adjustment.

The = operator is the opposite: it replaces that class's bits. chmod o= means "other gets exactly nothing," which is the cleanest way to say "close this to outsiders."


Changing permissions — octal form

The other dialect is octal: three digits, one per class, in the order owner, group, other. Each digit is the sum of three place values:

| Letter | Value | |--------|-------| | r | 4 | | w | 2 | | x | 1 |

Add the values of the switches that are on. The values 4, 2, 1 are powers of two, so every sum from 0 to 7 corresponds to exactly one combination, and you never have two ways to make the same digit.

| Desired | Arithmetic | Digit | |---------|-----------|-------| | rwx | 4+2+1 | 7 | | rw- | 4+2+0 | 6 | | r-x | 4+0+1 | 5 | | r-- | 4+0+0 | 4 | | -wx | 0+2+1 | 3 | | -w- | 0+2+0 | 2 | | --x | 0+0+1 | 1 | | --- | 0 | 0 |

Chain three digits and you have a whole mode:

chmod 751 sync_readings.sh   # owner rwx, group r-x, other --x
chmod 640 field_log.txt      # owner rw-, group r--, other ---

You can go backwards too. Given rw-r-----, split into rw-, r--, ---, which is 6, 4, 0, so 640.

Symbolic versus octal, side by side. The two dialects can say exactly the same thing:

| Intention | Symbolic | Octal | |-----------|----------|-------| | Owner reads and writes; nobody else gets anything | chmod u=rw,go= file | chmod 600 file | | Owner reads and writes; everyone else reads | chmod u=rw,go=r file | chmod 644 file | | Owner full; everyone else read and execute | chmod u=rwx,go=rx file | chmod 755 file | | Owner full; group read and execute; other execute only | chmod u=rwx,g=rx,o=x file | chmod 751 file |

A practical rule of thumb: use octal when you know the final state you want and are setting everything at once; use symbolic when you want to nudge one bit without disturbing the rest.


Design intent, not magic numbers

It is tempting to memorise a pile of numbers. Resist that. Each common mode is just the answer to a question: who needs what? Four modes cover most of your daily life:

  • 600 (rw-------) — a private draft. Only the owner can read or write. Use it for anything like notes/private_draft.txt that nobody else should see.
  • 644 (rw-r--r--) — a shared document. The owner edits, everyone may read. Typical for notes/field_log.txt or a summary page.
  • 755 (rwxr-xr-x) — a public script or directory. The owner may change it; everyone may run it or enter it. The usual mode for programs and for most folders.
  • 751 (rwxr-x--x) — a guarded script. The owner has everything, the group may read and run it, and others may only run it, not read the source.

Notice the pattern: scripts and directories need x, plain data files do not. If you create scripts/sync_readings.sh and the shell says "Permission denied" when you run it, the file almost certainly lacks x for your class. That is not a bug; it is the safety design working, because a downloaded text file is not allowed to run itself.

When you are unsure, begin with the tightest mode that still lets the work happen, and relax it only if someone has a real reason to need more.


Directories and the -R caution

You can apply a change to a directory and everything beneath it with -R (recursive):

chmod -R go-rwx tidewatch/notes

That reads as "for group and other, remove read, write, and execute on notes/ and everything inside it." It is powerful and quick, and that is exactly why it deserves caution.

Three habits will keep you safe:

  1. Print the path first. Run pwd and ls -l on the target so you know what you are about to change.
  2. Prefer symbolic form with -R. A command like chmod -R 644 tidewatch sets every item, directories included, to 644. That strips x from every folder, so you can no longer enter any of them. Symbolic - and + change only the bits you name, which is far gentler.
  3. Keep it inside the sandbox. Never aim -R at ~, /, or a path you typed from memory.

If you need to give directories x but not plain files, the capital X helps. In chmod -R u+rwX tidewatch, X adds execute only to directories (and to files that already had some execute bit). It is a tidy tool for the exact situation where one recursive command needs to treat the two kinds of item differently.


Common confusions

  • "I own the file, so I can always read it." Not if you removed your own r. Owners can usually change the mode back, but until they do, the bit rules apply to them too.
  • "The group digit is the first digit." No. Order is owner, group, other, left to right.
  • "777 fixes everything." It "fixes" access errors by letting everyone change and run everything. It is almost never the right answer; it just hides the question of who needs what.
  • "A file with w can be deleted by anyone who has w on the file." Deleting depends on the directory's w and x, not the file's own bits.

Self-study checklist

  • Decode rw-r----- into owner, group, and other letters, and give its octal form.
  • Set a file to owner read+write only using symbolic chmod, then using octal.
  • Explain, in your own words, why a directory without x cannot be entered.
  • Say which of 600, 644, 755, and 751 you would choose for a private draft, a public summary, a script everyone runs, and a script others may run but not read.
  • Explain why chmod -R 644 somefolder is risky.

Examples

Worked examples — permissions in the tidewatch project

Sam is working in the sandbox ~/cli-practice/tidewatch/. Each scene below follows the same rhythm: a small situation, the commands Sam types, what the output means, and one sentence to carry away. Type along if you can. Reading ls -l after every change is the habit that makes permissions feel ordinary rather than mysterious.

First, a little setup so every scene has something to work with:

cd ~/cli-practice
mkdir -p tidewatch/notes tidewatch/scripts tidewatch/data/raw
cd tidewatch
echo '#!/bin/sh' > scripts/sync_readings.sh
echo 'echo "syncing gauge readings"' >> scripts/sync_readings.sh
echo 'Draft: unusual surge at gauge A' > notes/private_draft.txt
echo 'gauge,level_cm' > data/raw/gauge_a.csv

Scene 1 — The script that refuses to run

Scene. Sam has written scripts/sync_readings.sh and wants to try it. A teammate said it should simply work.

./scripts/sync_readings.sh

The shell answers with something like:

zsh: permission denied: ./scripts/sync_readings.sh

(The wording differs between shells, but the words "permission denied" are the clue.)

Step 1: look before changing.

ls -l scripts/sync_readings.sh
-rw-r--r--  1 sam  crew  53 Oct 14 09:30 scripts/sync_readings.sh

Step 2: decode. After the leading - (regular file) comes rw- for the owner, r-- for the group, r-- for others. Look at the third character of each triple: all three are dashes. Nobody has x. Sam can read and edit the file, but the system will not run it.

Step 3: add execute for the owner only.

chmod u+x scripts/sync_readings.sh
ls -l scripts/sync_readings.sh
./scripts/sync_readings.sh
-rwxr--r--  1 sam  crew  53 Oct 14 09:30 scripts/sync_readings.sh
syncing gauge readings

Interpretation. Only the owner's triple changed, from rw- to rwx. The script runs for Sam, but a teammate in the group still cannot run it because the group triple is r--.

Takeaway. "Permission denied" on something you wrote is usually a missing x. Read the column, then add exactly the bit that is missing.


Scene 2 — Closing a private draft

Scene. Sam's notes/private_draft.txt contains early thoughts that are not ready to share.

ls -l notes/private_draft.txt
-rw-r--r--  1 sam  crew  32 Oct 14 09:35 notes/private_draft.txt

Step 1: read who can see it. The triples are rw-, r--, r--. The group and everyone else on the system can read this file. That is probably too open for a draft.

Step 2: decide the intent. Owner reads and writes; nobody else gets anything. The answer is 600. Doing the arithmetic: owner 4+2 = 6, group 0, other 0.

chmod 600 notes/private_draft.txt
ls -l notes/private_draft.txt
-rw-------  1 sam  crew  32 Oct 14 09:35 notes/private_draft.txt

Step 3: the symbolic way to get the same result. Suppose the file had been 644 again. This command reaches the same state:

chmod 644 notes/private_draft.txt
chmod go-rwx notes/private_draft.txt
ls -l notes/private_draft.txt

The final listing again shows -rw-------. The first line reopened the file; the second said "for group and others, remove everything."

Interpretation. go-rwx and 600 are two phrasings of one intention. Symbolic form says what to remove; octal form says what the final state is.

Takeaway. Pick the mode by asking "who needs what," then choose whichever dialect makes that sentence shortest.


Scene 3 — A corridor without a key

Scene. Sam wants to understand why directories need x, so tries an experiment on a folder Sam owns.

ls -ld data/raw

-d asks ls to describe the directory itself rather than listing its contents.

drwxr-xr-x  3 sam  crew  96 Oct 14 09:40 data/raw

Step 1: remove execute from the owner.

chmod u-x data/raw
ls -ld data/raw
cd data/raw
drw-r-xr-x  3 sam  crew  96 Oct 14 09:40 data/raw
cd: permission denied: data/raw

Step 2: see what still works.

ls data/raw
cat data/raw/gauge_a.csv

The first command may print the name gauge_a.csv, because r still allows reading the list of names. The second fails with "permission denied": reaching gauge_a.csv means passing through data/raw, and x is the pass-through bit.

Step 3: notice a surprise. The group and other triples still contain x, but Sam is still refused. That is because the system applies the first matching class only. Sam is the owner, so the owner triple rw- decides, and the more generous group bits are never consulted.

Step 4: repair.

chmod u+x data/raw
cd data/raw
pwd
cd ../..

Interpretation. r on a directory shows the list of names; x lets you travel through. Without x, the directory is a sealed corridor.

Takeaway. When cd says "permission denied," print the directory with ls -ld and look for a missing x in your own class's triple.


Scene 4 — A recursive change that went too far

Scene. Sam wants every file under data/ to be 644 so teammates can read the readings. Sam types the obvious thing:

chmod -R 644 data
cd data
cd: permission denied: data

Step 1: investigate.

ls -ld data
drw-r--r--  3 sam  crew   96 Oct 14 09:50 data

Step 2: interpret. -R 644 applied rw-r--r-- to everything, directories included. Every folder in the tree, data and data/raw alike, was set to rw-r--r-- and lost x for every class. Sam cannot enter data, so cannot reach anything below it.

Step 3: repair with the gentler tool. Capital X adds execute only to directories (and to files that already had an execute bit somewhere):

chmod -R u+rwX,go+rX data
ls -ld data data/raw
ls -l data/raw
drwxr-xr-x  3 sam  crew   96 Oct 14 09:50 data
drwxr-xr-x  3 sam  crew   96 Oct 14 09:50 data/raw
-rw-r--r--  1 sam  crew   14 Oct 14 09:42 gauge_a.csv

Interpretation. Directories regained x, and the plain file kept its data-only mode, because X does not give execute to ordinary files. The X rule repaired the parent folder first, which is what lets chmod carry on down into its children.

Takeaway. Before using -R, ask: "do files and folders need the same mode?" If not, use symbolic X, or change files and directories separately.


Scene 5 — Choosing between four familiar modes

Scene. Sam has four items and a teammate asks how each should be set. Sam answers by design intent, not by habit.

| Item | Who needs what | Mode | Reading | |------|----------------|------|---------| | notes/private_draft.txt | Only Sam reads and writes | 600 | rw------- | | notes/field_log.txt | Sam writes, team reads | 644 | rw-r--r-- | | scripts/sync_readings.sh (shared tool) | Sam edits, everyone runs | 755 | rwxr-xr-x | | scripts/sync_readings.sh (team-only) | Sam edits, group runs and reads, outsiders run only | 751 | rwxr-x--x |

Decoding 751 aloud. 7 is 4+2+1, so the owner has read, write, and execute. 5 is 4+1, so the group has read and execute. 1 is just execute, so others may run the script but cannot open it to read.

chmod 751 scripts/sync_readings.sh
ls -l scripts/sync_readings.sh
-rwxr-x--x  1 sam  crew  53 Oct 14 09:30 scripts/sync_readings.sh

Takeaway. Every mode on the table is an answer to a sentence. If you can say the sentence, you can find the digits.

Practice check — permissions

Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.

  1. 1.In `ls -l`, the first `-` in `-rw-r--r--` means…

  2. 2.Octal digit `5` means which permissions?

  3. 3.`chmod u+x file` …

  4. 4.Owner read+write, group and others no access — common octal mode?

  5. 5.Owner `rwx`, group `r-x`, other `--x` — which octal mode?

  6. 6.Sam owns the directory `tidewatch/data` and its mode is `rw-r--r--`. What happens on `cd tidewatch/data`?

  7. 7.Which command is the safest way to give every directory under `tidewatch` execute permission without making plain files executable?