What chmod does
chmod changes permissions (read r, write w, execute x) for three audiences:
- u (owner), g (group), o (others), and a (all = ugo)
Permissions mean different things for files vs directories:
- Files: r read, w modify, x run as a program.
- Directories: r list names, w create/delete/rename entries, x enter/traverse.
Check current perms:
ls -l file_or_dir
stat -c '%A %a %n' file_or_dir # shows symbolic & octal, e.g., rwxr-xr-- 754
Two ways to use chmod
1) Symbolic mode (add/remove/assign bits)
chmod [ugoa][+-=][rwxXst] file
Examples:
chmod u+x script.sh # owner gets execute
chmod g-w notes.txt # remove write from group
chmod a+r report.pdf # everyone gets read
chmod u=rw,go=r file.txt # owner rw, group/others r
chmod -R a+rX project/ # recursive: +r for all; +X gives x to dirs (and exec files)
Common letters
- r,w,x = read, write, execute
- X = execute only if item is a directory or any execute bit is already set (GNU extension; great for recursive fixes)
- s = setuid/setgid (advanced; see below)
- t = sticky bit (for shared dirs)
2) Octal (numeric) mode (set exact bits)
Digits are sums of r=4, w=2, x=1 for u/g/o:
chmod 755 script.sh # u=rwx (7), g=rx (5), o=rx (5)
chmod 640 file.txt # u=rw (6), g=r (4), o=--- (0)
chmod 750 dir/ # typical for private project dirs
Directories vs files (watch the x)
- To enter a directory, you need x on that directory.
- Typical patterns:
chmod 644 *.txt # files readable by all, editable by owner
chmod 755 bin/ -R # dirs & (maybe) files executable—often too broad
# Safer recursive pattern:
find myproj -type d -exec chmod 755 {} + # dirs: 755
find myproj -type f -exec chmod 644 {} + # files: 644
Recursive changes
chmod -R u+rwX,go-rwx project/ # owner rwX; remove all perms for group/others
chmod -R a+rX shared_docs/ # everyone can read; x only on dirs/execs
Special permission bits (exam-relevant)
Bit |
Where |
Meaning |
Set with … |
Octal |
setuid |
file |
run program with owner’s UID |
chmod u+s file |
add 4xxx |
setgid |
file |
run with group’s GID |
chmod g+s file |
add 2xxx |
setgid |
dir |
new files inherit dir’s group |
chmod g+s dir/ |
2xxx |
sticky |
dir |
only file owner can delete their files (e.g., /tmp) |
chmod +t dir/ |
1xxx |
Examples:
chmod 4755 /usr/local/bin/prog # setuid + 755
chmod 2775 /shared/team # setgid on shared dir
chmod 1777 /some/shared/tmp # sticky bit on shared tmp dir
Note: setuid on scripts is usually ignored for security. Use with care.
Handy options & tricks
chmod -R … path # recursive
chmod -v 644 file # verbose (show changes)
chmod -c 644 file # report only if changes were made
chmod --reference=REF F # copy perms from REF to F
The magic X (capital X)
chmod -R a+rX project/ # add execute only to directories (and already-exec files)
This is perfect for fixing a whole tree without making every file executable.
Common patterns you’ll use a lot
# Make a script runnable
chmod u+x run.sh
# Lock down a private dir
chmod 700 ~/.ssh
# Share a project within a group
chgrp -R devs /srv/app
chmod -R 2750 /srv/app # setgid on dirs + u=rwx,g=rx
# Web content (readable by all, owner edits)
chmod -R u=rwX,go=rX /var/www/html
Typical errors & fixes
- “Operation not permitted” → you’re not the owner (or FS is RO). Use sudo if appropriate, or chown by an admin.
- “Read-only file system” → the mount is read-only (e.g., recovery). Remount RW or choose another location.
- “No such file or directory” → path/glob typo; tab-complete to verify.
- Changed files but can’t enter directory → missing x on the directory; add +x for the audience that needs to traverse.
chmod vs umask
- umask controls default perms at creation time.
- chmod edits perms after
creation.
Common umask for teamwork: 002 (files become 664, dirs 775).
Student-safe guidelines
- Typical defaults: files 644, dirs 755; private work: files 640, dirs 750/700.
- Avoid chmod -R 777 (security & accidental edits). Use groups instead.
- For big trees, treat files and dirs separately (see find example above).
- Prefer a+rX over a+rx when going recursive.
Mini-lab (15–20 min)
mkdir -p ~/lab/chmod/{bin,docs,shared}
echo -e '#!/usr/bin/env bash\necho Hi' > ~/lab/chmod/bin/hello.sh
echo "Notes" > ~/lab/chmod/docs/notes.txt
# 1) scripts and files
chmod 644 ~/lab/chmod/bin/hello.sh
./lab/chmod/bin/hello.sh # should fail (no x)
chmod u+x ~/lab/chmod/bin/hello.sh && ~/lab/chmod/bin/hello.sh
# 2) fix a tree safely with X
chmod -R a+rX ~/lab/chmod/
find ~/lab/chmod -maxdepth 1 -type d -exec ls -ld {} \;
# 3) shared dir with setgid
sudo groupadd devs 2>/dev/null || true
sudo chgrp devs ~/lab/chmod/shared
chmod 2775 ~/lab/chmod/shared
ls -ld ~/lab/chmod/shared # look for the 's' in group perms
# 4) copy permissions from a reference file
touch ~/lab/chmod/template && chmod 640 ~/lab/chmod/template
chmod --reference=~/lab/chmod/template ~/lab/chmod/docs/notes.txt
stat -c '%A %a %n' ~/lab/chmod/docs/notes.txt
Exam-ready bullets
- chmod changes perms for u/g/o/a using symbolic (u+x, go-r) or octal (755, 640) modes.
- X adds execute only to dirs (and already-exec files) — great for recursion.
- Recursive: -R; treat dirs and files differently via find.
- Special bits: setuid(4xxx), setgid(2xxx), sticky(1xxx); setgid on dirs → new files inherit group.
- Use ls -l / stat -c '%A %a %n' to verify. Avoid 777; use groups and least privilege.