---
title: "Chmod"
description: "Complete chmod reference with numeric and symbolic permissions, special bits, directory permissions, and practical examples for managing file access"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/cheatsheets/chmod
---

# Chmod

Complete chmod reference covering file permissions, recursive changes with -v and -c, reference mode, logical operators, batch operations, practical examples, and security best practices for Linux file management.

## Getting Started

Introduction to chmod and permission fundamentals

### What is Chmod

Understanding chmod and file permissions in Unix-like systems

**Keywords:** chmod, permissions, access control, files, directories

#### Chmod overview and permissions concept

```bash
# Chmod stands for: change mode
# Used to change file and directory permissions

# Basic syntax: chmod [options] mode file
# Where mode can be:
#   - Octal notation: 755 (4 digits maximum)
#   - Symbolic notation: u+x, g-w, o=rx

# Permission components:
# user (u), group (g), other (o), all (a)
# read (r=4), write (w=2), execute (x=1)

# Key features:
# - Change owner/group/other permissions
# - Apply to files and directories
# - Recursive modification with -R
# - Special bits: setuid (4), setgid (2), sticky (1)
```

_exec_
```bash
ls -la /tmp/testfile.txt 2>/dev/null || touch /tmp/testfile.txt && ls -la /tmp/testfile.txt
```

_output_
```bash
-rw-r--r-- 1 user group 0 Feb 28 10:00 /tmp/testfile.txt
```

File permissions are displayed in ls -l output. The first 10 characters show type and permissions (rwxrwxrwx format).

- First character indicates file type (- for file, d for directory, l for link)
- Next 9 characters are permissions: 3 for user, 3 for group, 3 for other
- Read files before changing permissions
- Test changes on non-critical files first

#### Understanding permission string format

```bash
# Permission string format: -rwxrwxrwx
# Position 1: File type (- = file, d = directory, l = link, etc.)
# Positions 2-4: User (owner) permissions
# Positions 5-7: Group permissions
# Positions 8-10: Other permissions

# r (read) = 4
# w (write) = 2
# x (execute) = 1

# Examples:
# -rw-r--r-- = file, user: rw (6), group: r (4), other: r (4) = 644
# drwxr-xr-x = dir, user: rwx (7), group: rx (5), other: rx (5) = 755
# -rwx------ = file, user: rwx (7), group: none (0), other: none (0) = 700
```

_exec_
```bash
stat -c "%a %A %n" /tmp/testfile.txt
```

_output_
```bash
644 -rw-r--r-- /tmp/testfile.txt
```

The stat command displays permissions in both octal (644) and symbolic (-rw-r--r--) formats.

- Octal notation is more concise for scripts
- Symbolic notation is more readable for humans
- Both formats accomplish the same result
- 644 is common for files, 755 for directories

**Best practices:**

- Understand octal and symbolic notation before making changes
- Always verify permissions with ls -l after changing
- Use -v or -c flag to see what changed
- Test on non-critical files first

**Common errors:**

- **invalid mode**: Check syntax; use proper octal (0-7 digits) or symbolic notation
- **cannot access**: Provide correct file path and ensure you have permission to change it

### Installation and Setup

Verifying chmod availability and getting started

**Keywords:** install, setup, version, verify, help

#### Verify chmod installation

```bash
# Check if chmod is installed
which chmod

# Display chmod version (man page)
chmod --version 2>/dev/null || man chmod | head -20

# Show chmod help
man chmod | head -30

# Quick help
chmod --help 2>/dev/null | head -20
```

_exec_
```bash
which chmod
```

_output_
```bash
/bin/chmod
```

Chmod is a POSIX standard utility, always available on Unix-like systems at /bin/chmod or /usr/bin/chmod.

- Chmod is pre-installed on all Linux and Unix systems
- Part of coreutils package
- Available in POSIX-compliant systems
- No additional installation needed

#### Access chmod man pages for detailed reference

```bash
# Read full chmod manual
man chmod

# View specific sections
man chmod | grep -A 10 "DESCRIPTION"

# Search for specific permission
man chmod | grep -i "setuid"

# View examples
man chmod | grep -A 5 "EXAMPLES"
```

_exec_
```bash
chmod --help 2>&1 | head -15
```

_output_
```bash
Usage: chmod [OPTION]... MODE[,MODE]... FILE...
  or:  chmod [OPTION]... OCTAL-MODE FILE...
  or:  chmod [OPTION]... --reference=RFILE FILE...
Change the mode of each FILE to MODE.
-c, --changes          like -v but report only when a change is made
-f, --silent, --quiet  suppress most error messages
-v, --verbose          output a diagnostic for every file processed
-R, --recursive        change files and directories recursively
--reference=RFILE     use RFILE's mode instead of MODE values
```

The help and man pages provide comprehensive chmod reference documentation and usage examples.

- Man pages contain complete descriptions of all options
- Help flag varies between GNU and BSD versions
- Man page is most authoritative reference
- Online documentation available at man7.org

**Best practices:**

- Use man chmod as primary reference
- Check your system implementation (GNU vs BSD)
- Refer to official documentation for complex operations

**Common errors:**

- **chmod: command not found**: Not in PATH; check installation or PATH environment

## Basic Permissions

Understanding octal and symbolic notation for file permissions

### Octal Notation

Using numerical octal format for specifying permissions

**Keywords:** octal, numeric, notation, digits, 644, 755

#### Understanding octal notation basics

```bash
# Octal notation uses 3-4 digits
# Each digit represents a category:
# Position 1 (optional): Special bits (setuid=4, setgid=2, sticky=1)
# Position 2: User/Owner permissions
# Position 3: Group permissions
# Position 4: Other permissions

# Each permission has a value:
# r (read) = 4
# w (write) = 2
# x (execute) = 1

# Examples of octal modes:
# 644 = rw-r--r-- (file: owner rw, group r, other r)
# 755 = rwxr-xr-x (directory: owner rwx, group rx, other rx)
# 700 = rwx------ (private: only owner can access)
# 777 = rwxrwxrwx (full: all can read/write/execute)
```

_exec_
```bash
touch /tmp/testfile.txt && chmod 644 /tmp/testfile.txt && ls -l /tmp/testfile.txt
```

_output_
```bash
-rw-r--r-- 1 user group 0 Feb 28 10:00 /tmp/testfile.txt
```

Chmod 644 sets owner read+write, group read, other read permissions (6+4+4=644).

- 644 is standard for regular files
- 755 is standard for directories
- 600 is for private files only owner can access
- 777 is rarely needed and less secure

#### Common octal permission modes

```bash
# Commonly used octal modes:

# 755: rwxr-xr-x (directories, executables)
# Owner: full access, Group/Other: read and execute only

# 644: rw-r--r-- (regular files)
# Owner: read and write, Group/Other: read only

# 700: rwx------ (private - owner only)
# Only owner has all permissions

# 600: rw------- (private file - owner only)
# Owner read/write, no access for group/other

# 775: rwxrwxr-x (group-writable)
# Owner/Group have full access, other read/execute

# 666: rw-rw-rw- (all can read/write)
# All users can read and write (uncommon, less secure)

# 444: r--r--r-- (read-only for all)
# All users can read, none can write/execute
```

_exec_
```bash
cd /tmp && touch file_644 file_755 file_700 && chmod 644 file_644 && chmod 755 file_755 && chmod 700 file_700
ls -la file_* | awk '{print $1, $9}'
```

_output_
```bash
-rw-r--r-- file_644
-rwxr-xr-x file_755
-rwx------ file_700
```

Different octal modes produce different permission strings. 644 allows owner write, 755 allows execution, 700 restricts access to owner.

- 644 and 755 are most commonly used
- 700 for sensitive files (private keys, config)
- 775 for collaborative team files
- 666 and 777 rarely used due to security concerns

**Best practices:**

- Use 644 for regular files, 755 for directories
- Use 700 for private files and configuration
- Avoid 777 permissions unless absolutely necessary
- Document why you're using non-standard permissions

**Common errors:**

- **Invalid octal value**: Ensure each digit is 0-7, no 8 or 9
- **Permission denied**: Ensure you own the file or are running as root

### Symbolic Notation

Using symbolic format (u/g/o/a ±= rwxXst) for permissions

**Keywords:** symbolic, notation, u, g, o, a, rwx, operators

#### Understanding symbolic notation syntax

```bash
# Symbolic notation syntax: [ugoa]*([-+=][perms...]...)
# Who: u=user, g=group, o=other, a=all (default)
# Operator: + (add), - (remove), = (set exactly)
# Permissions: r (read), w (write), x (execute)
#            : X (execute if already executable)
#            : s (setuid/setgid), t (sticky)

# Examples:
# u+x       Add execute for user
# g-w       Remove write from group
# o=        Remove all permissions from other
# a+r       Add read for all
# u+x,g+x   Multiple changes in one command
# g=r       Set group to read-only
# a=        Remove all permissions for all users
```

_exec_
```bash
touch /tmp/sym_test.txt && chmod u+x /tmp/sym_test.txt && ls -l /tmp/sym_test.txt
```

_output_
```bash
-rwxr--r-- 1 user group 0 Feb 28 10:00 /tmp/sym_test.txt
```

u+x adds execute permission for the user. Starting from 644 (-rw-r--r--), it becomes 744 (-rwxr--r--).

- Symbolic notation builds on existing permissions
- Use + to add, - to remove, = to set exactly
- Easier to remember than octal for common changes
- More readable in scripts and documentation

#### Common symbolic notation examples

```bash
# Add write permission for user
chmod u+w file.txt

# Remove execute from all
chmod a-x file.sh

# Set group to read-only
chmod g=r file.txt

# Add execute if already readable
chmod u+X file.txt

# Remove all permissions except user read
chmod a-rwx,u+r file.txt

# Make readable by all
chmod a+r file.txt

# Make directory traversable by group
chmod g+x directory

# Make file non-writable by anyone
chmod a-w file.txt

# Give user all, group read/execute, other nothing
chmod u=rwx,g=rx,o= file.txt
```

_exec_
```bash
touch /tmp/sym_demo.txt && chmod 644 /tmp/sym_demo.txt
echo "Before: $(ls -l /tmp/sym_demo.txt | awk '{print $1}')"
chmod u+w,g+w /tmp/sym_demo.txt
echo "After: $(ls -l /tmp/sym_demo.txt | awk '{print $1}')"
```

_output_
```bash
Before: -rw-r--r--
After: -rw-rw-r--
```

u+w,g+w adds write permission for both user and group. Multiple changes are separated by commas.

- Chain multiple changes with commas
- No spaces between changes
- More readable than octal for humans
- Better for documenting intent in scripts

**Best practices:**

- Use symbolic notation for clarity and readability
- Use = sparingly, prefer + and - for incremental changes
- Test on non-critical files first
- Document complex permission changes

**Common errors:**

- **invalid mode**: Check syntax; use proper user/group/other values and operators
- **No spaces between changes**: Write u+x,g+x not u+x, g+x

### Understanding rwx Permissions

Detailed explanation of read, write, and execute permissions

**Keywords:** read, write, execute, r, w, x, permissions

#### Read permission (r) explained

```bash
# Read permission (r) = 4
# For files: Allows reading/viewing file contents
# For directories: Allows listing directory contents with ls

# File with read permission:
# Can: cat, less, grep, copy the file
# Cannot: run/execute file, modify file

# Directory with read permission:
# Can: list files with ls
# Cannot: enter directory (cd), access files
# Note: Need execute for directory access

# Example:
# r--r--r-- (444)
# File is readable by all, not writable
```

_exec_
```bash
touch /tmp/read_test.txt && echo "test content" > /tmp/read_test.txt && chmod 444 /tmp/read_test.txt
echo "=== File status (r--r--r--) ===" && ls -l /tmp/read_test.txt
echo "=== Can read file ===" && cat /tmp/read_test.txt
```

_output_
```bash
=== File status (r--r--r--) ===
-r--r--r-- 1 user group 12 Feb 28 10:00 /tmp/read_test.txt
=== Can read file ===
test content
```

Read permission (444) allows viewing file contents but prevents modification or execution.

- Read is required to view file or list directory
- For directories, read alone doesn't allow cd
- For files, read doesn't allow execution
- Read-only files cannot be deleted by non-owners

#### Write permission (w) explained

```bash
# Write permission (w) = 2
# For files: Allows modifying/deleting file contents
# For directories: Allows creating/deleting files in directory

# File with write permission:
# Can: modify, overwrite, append, truncate file
# Cannot: if no read, cannot see current contents

# Directory with write permission:
# Can: create new files, delete existing files
# Can: rename files, modify directory contents
# Note: Still needs execute to access files in it

# Example:
# -w--w--w- (222)
# All users can write/modify
```

_exec_
```bash
touch /tmp/write_test.txt && chmod 644 /tmp/write_test.txt && echo "original" > /tmp/write_test.txt
echo "=== Start content ===" && cat /tmp/write_test.txt
chmod 666 /tmp/write_test.txt && echo "modified" >> /tmp/write_test.txt
echo "=== After chmod 666 and write ===" && cat /tmp/write_test.txt
```

_output_
```bash
=== Start content ===
original
=== After chmod 666 and write ===
original
modified
```

Write permission (666) allows modification of file contents. Without it, the file is read-only.

- Write requires modify/delete permission
- Write on file allows content changes
- Write on directory allows creating/deleting files
- Owner can delete own file even without write with write directory

#### Execute permission (x) explained

```bash
# Execute permission (x) = 1
# For files: Allows running/executing file (scripts, binaries)
# For directories: Allows entering directory (cd), accessing files/subdirs

# File with execute permission:
# Can: run if it's a script or binary
# Still needs read to execute scripts (interpreter needs to read)

# Directory with execute permission:
# Can: cd into directory, access contents
# Core permission needed for directory access
# Note: Still needs read to list, execute to access

# Example:
# rwxr-xr-x (755) - directory mode
# Allows owner full, group/other can view and access
```

_exec_
```bash
mkdir -p /tmp/exec_test && chmod 755 /tmp/exec_test && touch /tmp/exec_test/file.txt
echo "=== Directory with execute (755) ===" && ls -ld /tmp/exec_test
echo "=== Can access directory and list contents ===" && ls /tmp/exec_test
```

_output_
```bash
=== Directory with execute (755) ===
drwxr-xr-x 2 user group 4096 Feb 28 10:00 /tmp/exec_test
=== Can access directory and list contents ===
file.txt
```

Execute permission on directories (755) allows entering and accessing the directory. For files, it allows execution.

- Execute on directory = can cd into it
- Execute on file = can run it (if read also present for scripts)
- Directories typically get 755, files 644 or 755
- Execute bit essential for directory traversal

**Best practices:**

- [object Object]
- Files typically 644 (read/write for owner, read for group/other)
- Directories typically 755 (full owner, read/execute for group/other)
- Consider security when setting permissions

**Common errors:**

- **Permission denied when reading**: File lacks read (r) permission
- **Cannot execute script**: File lacks execute (x) and possibly read permission
- **Cannot access directory**: Directory lacks execute (x) permission for your user

## User/Group/Other Permissions

Managing permissions for owner, group, and other users

### User Permissions

Setting and managing owner/user permissions

**Keywords:** user, owner, u, permissions, owner-permissions

#### Setting user-only permissions

```bash
# Set permissions for owner/user only
# u=rwx (user has all permissions, group/other have none)

# Common user-only patterns:
# u=rwx,g=,o= or 700 - owner full access only
# u=rw (read/write for owner)
# u+x (add execute for owner)
# u-w (remove write from owner)

# Examples:
chmod u=rwx file.sh      # owner full access
chmod 700 private.key    # private file - owner only
chmod u+x script.sh      # make script executable by owner
chmod u-w readonly.txt   # make file read-only for owner
```

_exec_
```bash
touch /tmp/user_perm.txt && chmod 600 /tmp/user_perm.txt && ls -l /tmp/user_perm.txt
```

_output_
```bash
-rw------- 1 user group 0 Feb 28 10:00 /tmp/user_perm.txt
```

Chmod 600 (u=rw,g=,o=) allows owner read and write, no access for group or other.

- 600 is appropriate for sensitive files
- 700 for directories only owner can access
- User permissions are inherited by file creator
- Owner can change permissions only on own files (unless root)

#### Adding and removing user permissions

```bash
# Add execute permission for user
chmod u+x file.sh

# Remove write permission for user
chmod u-w file.txt

# Add read and execute
chmod u+rx file

# Remove all user permissions
chmod u= file.txt

# Reset user to basic read/write
chmod u=rw file.txt

# Add write back to user
chmod u+w file.txt
```

_exec_
```bash
touch /tmp/user_mod.txt && chmod 644 /tmp/user_mod.txt
echo "Initial: $(ls -l /tmp/user_mod.txt | awk '{print $1}')"
chmod u+x /tmp/user_mod.txt
echo "After u+x: $(ls -l /tmp/user_mod.txt | awk '{print $1}')"
chmod u-r /tmp/user_mod.txt
echo "After u-r: $(ls -l /tmp/user_mod.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-r--r--
After u+x: -rwxr--r--
After u-r: --wxr--r--
```

User permissions can be modified individually. u+x adds execute, u-r removes read from the owner.

- Changes are additive with +, subtractive with -
- = sets exactly what you specify
- Other permissions unchanged unless specified
- Always verify with ls -l after changes

**Best practices:**

- Use u= to reset user permissions to specific state
- Use u+x/u-x for incremental changes
- Verify changes with ls -l
- Document unusual user permission settings

**Common errors:**

- **Cannot execute script**: Add u+x permission with chmod u+x script.sh
- **Cannot modify file**: Add u+w with chmod u+w file.txt

### Group Permissions

Managing group permissions for shared files

**Keywords:** group, g, group-permissions, collaboration, team

#### Setting group permissions

```bash
# Set permissions for group members
# g=rx (group can read and execute)
# g+w (add write for group)
# g-x (remove execute from group)

# Common group patterns:
# g=r (group read-only)
# g=rx (group read and execute - typical for directories)
# g=rw (group read and write - for shared files)
# g= (remove all group permissions)

# Examples:
chmod g=r file.txt       # group read-only
chmod g+w file.txt       # add write for group
chmod g-x directory      # remove execute from group
chmod g= file.txt        # remove all group permissions
```

_exec_
```bash
touch /tmp/group_perm.txt && chmod 640 /tmp/group_perm.txt && ls -l /tmp/group_perm.txt
```

_output_
```bash
-rw-r----- 1 user group 0 Feb 28 10:00 /tmp/group_perm.txt
```

Chmod 640 (u=rw,g=r,o=) allows owner read/write and group read, no access for others.

- 640 is common for files shared with group
- 750 is common for directories shared with group
- Group must include relevant users
- More restrictive than world-readable
- Good for team collaboration

#### Collaborative file sharing with group permissions

```bash
# File shared with group, readable and writable by all group members
chmod g+rw file.txt

# Directory shared with group, all can access and add files
chmod g+rw directory/
chmod g+x directory/

# Make group permissions match user
chmod g=u file.txt

# Remove write from group
chmod g-w file.txt

# Set standard collaboration mode
chmod g=rx directory/

# Add group permissions without changing others
chmod g+w file.txt
```

_exec_
```bash
touch /tmp/collab.txt && chmod 644 /tmp/collab.txt
echo "Initial: $(ls -l /tmp/collab.txt | awk '{print $1}')"
chmod g+w /tmp/collab.txt
echo "After g+w: $(ls -l /tmp/collab.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-r--r--
After g+w: -rw-rw-r--
```

g+w adds write permission for the group. This allows group members to modify the file.

- g+w enables group write access
- Useful for shared project files
- Verify group membership with id command
- Set before sharing with team members

**Best practices:**

- Use g=r for read-only group access
- Use g=rx for group directory access
- Use g+w carefully for shared files
- Document group permissions for team files

**Common errors:**

- **Group cannot write file**: Add g+w with chmod g+w file.txt
- **Group cannot access directory**: Add g+x with chmod g+x directory/

### Other Permissions

Managing permissions for all other users

**Keywords:** other, o, world, public, unrestricted

#### Setting permissions for others

```bash
# Set permissions for other/world users
# o=r (other can only read)
# o+x (add execute for other - allow others to access)
# o= (remove all permissions from other/world)

# Common patterns:
# o= (completely private, except user/group)
# o=r (world readable)
# o=rx (world readable and executable - common for web)
# o+r (add read for others)

# Examples:
chmod o=r file.txt       # world readable only
chmod o= file.txt        # private, no world access
chmod o+r file.txt       # add read for others
chmod o-r file.txt       # remove read from others
```

_exec_
```bash
touch /tmp/other_perm.txt && echo "content" > /tmp/other_perm.txt && chmod 600 /tmp/other_perm.txt && ls -l /tmp/other_perm.txt
```

_output_
```bash
-rw------- 1 user group 0 Feb 28 10:00 /tmp/other_perm.txt
```

Chmod 600 removes all permissions from group and other. Only the owner can access the file.

- 600 is for completely private files
- Others have no access at all
- Appropriate for sensitive data
- Prevents accidental exposure

#### World-readable and accessible files

```bash
# Make file world-readable
chmod o+r file.txt

# Make directory world-accessible with readable contents
chmod o+rx directory/

# Make web content accessible
chmod o=rx script.sh

# Add world-accessible read
chmod a+r file.txt (adds read for all: user, group, other)

# Remove world access entirely
chmod o= file.txt

# World-readable, user/group writable
chmod 664 file.txt
```

_exec_
```bash
touch /tmp/world.txt && chmod 640 /tmp/world.txt
echo "Initial: $(ls -l /tmp/world.txt | awk '{print $1}')"
chmod o+r /tmp/world.txt
echo "After o+r: $(ls -l /tmp/world.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-r-----
After o+r: -rw-r--r--
```

o+r adds read permission for others. The file becomes world-readable (644).

- o+r makes file readable by any user
- Useful for public files and web content
- Be careful with sensitive data
- Web files typically need o=r or o=rx

**Best practices:**

- Use o= for private files
- Use o=r for public data files
- Use o=rx for executable scripts and directories
- Be cautious with world-writable permissions (o=w is rarely appropriate)

**Common errors:**

- **Others cannot read file**: Add o+r with chmod o+r file.txt
- **Others cannot access directory**: Add o+x with chmod o+x directory/

### All Permissions (a)

Managing permissions for all users at once

**Keywords:** all, a, everyone, user, group, other

#### Setting permissions for all users

```bash
# Set permissions for all users (user, group, other)
# a=r (read-only for everyone)
# a=rx (read and execute for everyone)
# a+r (add read for all)
# a-w (remove write from all)
# a= (remove all permissions - be careful!)

# Common patterns:
# a=r (world readable, no write/execute)
# a=rx (world readable and executable)
# a-w (remove write from everyone)
# a+r (add read for everyone)

# Examples:
chmod a+r file.txt       # readable by all
chmod a-w file.txt       # no one can write
chmod a+x file.sh        # executable by all
chmod a= file.txt        # remove all permissions
```

_exec_
```bash
touch /tmp/all_perm.txt && chmod 700 /tmp/all_perm.txt
echo "Initial: $(ls -l /tmp/all_perm.txt | awk '{print $1}')"
chmod a+r /tmp/all_perm.txt
echo "After a+r: $(ls -l /tmp/all_perm.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rwx------
After a+r: -rwxr--r--
```

a+r adds read permission for all users. Starting from 700, it becomes 744 (rwxr--r--).

- a= without modification removes all permissions (be careful!)
- a is default if no user specified (u+x is same as a+x? No, actually u+x means user only)
- a+r adds read for user, group, and other
- a-w removes write from all three categories

#### Batch permission changes for all users

```bash
# Add read for all users
chmod a+r file.txt

# Remove write from all
chmod a-w file.txt

# Make fully public readable/executable
chmod a+rx directory/

# Remove all permissions (make inaccessible)
chmod a= file.txt

# Set standard read-only
chmod a=r file.txt

# Set standard read and execute for all
chmod a=rx script.sh

# Remove execute from all (no one can run)
chmod a-x file.sh
```

_exec_
```bash
touch /tmp/batch.txt && chmod 644 /tmp/batch.txt
echo "Initial: $(ls -l /tmp/batch.txt | awk '{print $1}')"
chmod a-w /tmp/batch.txt
echo "After a-w: $(ls -l /tmp/batch.txt | awk '{print $1}')"
chmod a=r /tmp/batch.txt
echo "After a=r: $(ls -l /tmp/batch.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-r--r--
After a-w: -r--r--r--
After a=r: -r--r--r--
```

a-w removes write from all users. a=r sets all users to read-only permission.

- a+r and a-w are quick ways to set permissions for everyone
- a= is dangerous and rarely used
- Prefer specific u/g/o for clarity
- a is useful for quick batch changes

**Best practices:**

- Use a+r to make files readable by all
- Use a-w to prevent accidental modifications
- Use a=r for read-only files for everyone
- Avoid a= (removes all permissions)

**Common errors:**

- **All permissions removed**: You used a=, use a=r instead to set read-only
- **Cannot execute script for anyone**: Add execute with chmod a+x script.sh

## Operators

Understanding chmod operators for modifying permissions

### Adding Permissions

Adding permissions with the + operator

**Keywords:** add, plus, operator, plus-equals

#### Adding permissions with + operator

```bash
# Add permissions with + operator
# Syntax: chmod [ugoa]+[rwxXst] file

# Examples:
chmod u+r file.txt      # add read for user
chmod u+w file.txt      # add write for user
chmod u+x file.txt      # add execute for user
chmod g+r file.txt      # add read for group
chmod o+x directory/    # add execute for other
chmod a+r file.txt      # add read for all

# Multiple permissions at once:
chmod u+rwx file.txt    # add read, write, execute for user
chmod g+rx file.txt     # add read and execute for group
chmod a+x script.sh     # add execute for all
```

_exec_
```bash
touch /tmp/add_test.txt && chmod 000 /tmp/add_test.txt
echo "Initial: $(ls -l /tmp/add_test.txt | awk '{print $1}')"
chmod u+r /tmp/add_test.txt
echo "After u+r: $(ls -l /tmp/add_test.txt | awk '{print $1}')"
chmod u+w /tmp/add_test.txt
echo "After u+w: $(ls -l /tmp/add_test.txt | awk '{print $1}')"
```

_output_
```bash
Initial: ----------
After u+r: -r--------
After u+w: -rw-------
```

The + operator adds permissions incrementally. Each chmod command adds without removing existing permissions.

- + adds permissions without affecting other bits
- Can add multiple at once (u+rwx)
- Non-destructive - existing permissions retained
- Ideal for incremental permission changes

#### Combining multiple additions in one command

```bash
# Add multiple permissions in one command
chmod u+rwx,g+rx,o+r file.txt

# Make executable by all without changing other bits
chmod a+x script.sh

# Add read and write for user and group
chmod u+rw,g+rw file.txt

# Add write for group and other
chmod g+w,o+w file.txt

# Add execute for user only
chmod u+x file.sh

# Add read for group and other
chmod g+r,o+r file.txt
```

_exec_
```bash
touch /tmp/multi_add.txt && chmod 600 /tmp/multi_add.txt
echo "Initial: $(ls -l /tmp/multi_add.txt | awk '{print $1}')"
chmod g+r,o+r /tmp/multi_add.txt
echo "After g+r,o+r: $(ls -l /tmp/multi_add.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-------
After g+r,o+r: -rw-r--r--
```

Multiple additions with + can be combined with commas. User permissions unchanged, group and other now have read.

- Use commas to separate multiple operations
- Each part is applied in sequence
- Previous permissions are preserved
- Efficient way to set complex permissions

**Best practices:**

- Use + for non-destructive permission changes
- Add only necessary permissions, avoid over-permissive settings
- Use commas to combine changes in one command
- Verify result with ls -l

**Common errors:**

- **Syntax error in mode**: Ensure no spaces before/after + (u+r, not u + r)
- **Permission not added**: Verify correct user/group/other specified

### Removing Permissions

Removing permissions with the - operator

**Keywords:** remove, minus, operator, revoke

#### Removing permissions with - operator

```bash
# Remove permissions with - operator
# Syntax: chmod [ugoa]-[rwxXst] file

# Examples:
chmod u-r file.txt      # remove read from user
chmod u-w file.txt      # remove write from user
chmod u-x file.txt      # remove execute from user
chmod g-w file.txt      # remove write from group
chmod o-r file.txt      # remove read from other
chmod a-x script.sh     # remove execute from all

# Multiple permissions at once:
chmod u-rwx file.txt    # remove all from user
chmod g-rx file.txt     # remove read and execute from group
chmod a-w file.txt      # remove write from all
```

_exec_
```bash
touch /tmp/rem_test.txt && chmod 777 /tmp/rem_test.txt
echo "Initial: $(ls -l /tmp/rem_test.txt | awk '{print $1}')"
chmod o-r /tmp/rem_test.txt
echo "After o-r: $(ls -l /tmp/rem_test.txt | awk '{print $1}')"
chmod a-w /tmp/rem_test.txt
echo "After a-w: $(ls -l /tmp/rem_test.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rwxrwxrwx
After o-r: -rwxrwx---
After a-w: -r-xr-x---
```

The - operator removes specific permissions. Files progress from 777 to 770 to 555.

- removes permissions without affecting other bits
- Can remove multiple at once (u-rwx)
- Non-destructive - other permissions retained
- Ideal for revoking specific access

#### Revoking access and tightening security

```bash
# Remove write permission from insecure files
chmod a-w file.txt

# Revoke group write access
chmod g-w file.txt

# Remove other's read access
chmod o-r file.txt

# Remove all permissions from other
chmod o-rwx file.txt

# Remove write for user and group
chmod u-w,g-w file.txt

# Revoke execute from script
chmod a-x script.sh

# Remove group and other access entirely
chmod go-rwx file.txt (same as chmod u=rwx file.txt)
```

_exec_
```bash
touch /tmp/secure.txt && chmod 644 /tmp/secure.txt
echo "Initial: $(ls -l /tmp/secure.txt | awk '{print $1}')"
chmod g-r,o-r /tmp/secure.txt
echo "After g-r,o-r: $(ls -l /tmp/secure.txt | awk '{print $1}')"
chmod a-w /tmp/secure.txt
echo "After a-w: $(ls -l /tmp/secure.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rw-r--r--
After g-r,o-r: -rw-------
After a-w: -r--------
```

Removing permissions progressively tightens access. File goes from 644 to 600 to 400.

- Useful for security hardening
- Removes only specified permissions
- Other permissions preserved
- Good practice for preventing accidental modifications

**Best practices:**

- Use - to remove unnecessary permissions
- Remove at least o (other) read for private files
- Remove write for read-only files
- Verify changes with ls -l

**Common errors:**

- **Cannot remove permission already gone**: No error; removing non-existent permission is safe
- **Accidentally removed needed permission**: Use + to add it back

### Setting Exact Permissions

Setting permissions to exact state with = operator

**Keywords:** set, exact, equals, operator, absolute

#### Setting exact permissions with = operator

```bash
# Set exact permissions with = operator
# Syntax: chmod [ugoa]=[rwxXst] file
# Note: = sets ONLY what you specify, removes everything else

# Examples:
chmod u=rwx file.txt     # user has rwx, nothing else
chmod g=r file.txt       # group has r, nothing else
chmod o= file.txt        # other has nothing
chmod a=r file.txt       # all have r only, no w or x

# Setting entire perms:
chmod u=rwx,g=rx,o=rx directory/  # sets 755
chmod u=rw,g=r,o=r file.txt       # sets 644
chmod u=rwx,g=,o= file.txt        # sets 700
```

_exec_
```bash
touch /tmp/set_test.txt && chmod 777 /tmp/set_test.txt
echo "Initial: $(ls -l /tmp/set_test.txt | awk '{print $1}')"
chmod u=rw /tmp/set_test.txt
echo "After u=rw: $(ls -l /tmp/set_test.txt | awk '{print $1}')"
chmod g=r,o= /tmp/set_test.txt
echo "After g=r,o=: $(ls -l /tmp/set_test.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rwxrwxrwx
After u=rw: -rw-rwxrwx
After g=r,o=: -rw-r-----
```

The = operator sets exact permissions for specified category. Unspecified categories retain existing permissions.

- = completely resets specified user/group/other
- Unmodified categories keep their permissions
- More destructive than + or -
- Useful for setting standard modes

#### Setting standard permission modes

```bash
# Set standard 644 (file) permissions
chmod u=rw,g=r,o=r file.txt

# Set standard 755 (directory) permissions
chmod u=rwx,g=rx,o=rx directory/

# Set private 600 permissions
chmod u=rw,g=,o= private.key

# Set private directory 700
chmod u=rwx,g=,o= private_dir/

# Set collaborative 770
chmod u=rwx,g=rwx,o= shared.txt

# Set read-only for all
chmod u=r,g=r,o=r readonly.txt

# Set execute for all
chmod u=x,g=x,o=x execute.sh
```

_exec_
```bash
touch /tmp/std_644.txt && chmod u=rw,g=r,o=r /tmp/std_644.txt && ls -l /tmp/std_644.txt | awk '{print $1}'
```

_output_
```bash
-rw-r--r--
```

Setting u=rw,g=r,o=r creates standard 644 permissions. User gets read/write, group and other get read only.

- Useful for enforcing standard modes
- More verbose than octal but clearer intent
- Equivalent to octal chmod 644
- Good for documentation and scripts

**Best practices:**

- Use = carefully; it's more destructive than + or -
- Prefer + and - for incremental changes
- Use = when you need absolute control
- Document why you're using = operator

**Common errors:**

- **Unexpected permissions after chmod**: Remember = sets ONLY what specified; other categories still have old permissions
- **Using =  when you mean +**: Use u+x not u=x for adding execute

### Multiple Changes

Combining multiple permission changes in one command

**Keywords:** multiple, changes, comma, combined, chaining

#### Chaining multiple permission changes

```bash
# Combine multiple changes with commas
# Syntax: chmod change1,change2,change3 file

# Examples:
chmod u+rx,g+r,o-rw file.txt    # add user rx, add group r, remove other rw
chmod u=rw,g=r,o=r file.txt     # set user rw, group r, other r (644)
chmod a+r,a-w file.txt          # add read for all, remove write from all
chmod u+x,g+x,o+x file.sh       # make executable for all

# Complex multi-step changes:
chmod g-w,o-x file.txt          # revoke group write and other execute
chmod u-rwx,g-rwx,o-rwx file.txt # remove all permissions

# Setting up standard modes in one go:
chmod u=rwx,g=rx,o=rx script.sh # set 755 for executable
chmod u=rw,g=,o= secrets.key    # set 600 for private key
```

_exec_
```bash
touch /tmp/multi_change.txt && chmod 777 /tmp/multi_change.txt
echo "Initial: $(ls -l /tmp/multi_change.txt | awk '{print $1}')"
chmod u=rw,g=r,o= /tmp/multi_change.txt
echo "After multi-change: $(ls -l /tmp/multi_change.txt | awk '{print $1}')"
```

_output_
```bash
Initial: -rwxrwxrwx
After multi-change: -rw-r-----
```

Multiple changes separated by commas are applied sequentially. One command sets user=rw, group=r, other nothing.

- Comma-separated changes applied left to right
- No spaces allowed around commas
- More efficient than multiple chmod commands
- Useful in scripts for atomicity

#### Real-world permission setup scenarios

```bash
# Setup web server script (700 but user only)
chmod u=rwx,g=,o= /etc/init.d/myserver

# Setup configuration file (owner only rw)
chmod u=rw,g=,o= /etc/myapp/config

# Setup log file (owner rw, group r)
chmod u=rw,g=r,o= /var/log/myapp.log

# Setup public html (all can read)
chmod u=rw,g=r,o=r /var/www/html/index.html

# Setup shared directory (team collaboration)
chmod u=rwx,g=rwx,o=rx /home/team/shared/

# Setup sensitive data (owner only)
chmod u=r,g=,o= ~/.ssh/id_rsa

# Setup executable script (owner rwx, group/other rx)
chmod u=rwx,g=rx,o=rx /usr/local/bin/myscript
```

_exec_
```bash
mkdir -p /tmp/setup_demo && touch /tmp/setup_demo/{config,script,data}
chmod u=rw,g=,o= /tmp/setup_demo/config
chmod u=rwx,g=rx,o= /tmp/setup_demo/script
chmod u=rw,g=r,o=r /tmp/setup_demo/data
ls -l /tmp/setup_demo/
```

_output_
```bash
total 0
-rw------- 1 user group 0 Feb 28 10:00 config
-rwxr-x--- 1 user group 0 Feb 28 10:00 script
-rw-r--r-- 1 user group 0 Feb 28 10:00 data
```

Multiple changes efficiently set up files with appropriate permissions for config (private), script (executable), and data (readable).

- Combines multiple chmod operations into single command
- More efficient than separate chmod calls
- Atomicity helps in scripts and batch operations
- Clear intention with multiple changes

**Best practices:**

- Use commas without spaces to separate changes
- Apply changes left to right in sequence
- Group related changes together
- Test on non-critical files first

**Common errors:**

- **Invalid mode**: Remove spaces around commas; use u+x,g+x not u+x, g+x
- **Unexpected results**: Remember changes applied in order; verify final state

## Special Permissions

Understanding and using setuid, setgid, and sticky bit

### Setuid Bit

Understanding and using the setuid special permission

**Keywords:** setuid, suid, special, 4000, setuid-bit

#### Understanding setuid bit

```bash
# Setuid (Set User ID) bit = 4000
# When set on executable file:
# - File executes with owner's permissions, not executor's
# - Only valid on executable files (not directories)
# - Shown as 's' in user execute position (rwsr-xr-x)

# In octal notation:
# First digit: 4 = setuid
# chmod 4755 = -rwsr-xr-x (setuid + rwxr-xr-x)
# chmod 4750 = -rwsr-x--- (setuid + rwxr-x---)

# Symbolic notation:
# chmod u+s file.sh     # add setuid bit
# chmod u-s file.sh     # remove setuid bit

# Use cases:
# - Password utilities (passwd, sudo)
# - System maintenance tools
# - Allows unprivileged users to temporarily gain elevated access
```

_exec_
```bash
touch /tmp/suid_test.sh && chmod 755 /tmp/suid_test.sh && chmod u+s /tmp/suid_test.sh
ls -l /tmp/suid_test.sh
```

_output_
```bash
-rwsr-xr-x 1 user group 0 Feb 28 10:00 /tmp/suid_test.sh
```

The 's' in the user execute position indicates setuid is set. The file executes with owner's permissions.

- Setuid shown as 's' replacing 'x' if execute present, 'S' if not
- Dangerous on frequently-used files
- Never use setuid on shell scripts if possible
- Binary (compiled) programs are safer with setuid

#### Setting and viewing setuid bits

```bash
# Add setuid bit
chmod u+s /usr/bin/somecommand
chmod 4755 /usr/bin/somecommand

# Remove setuid bit
chmod u-s /usr/bin/somecommand
chmod 755 /usr/bin/somecommand

# Verify setuid is set
ls -l /usr/bin/somecommand  # look for 's' in position 3
stat /usr/bin/somecommand

# View files with setuid set
find /usr/bin -perm -4000

# View as 4-digit octal
stat -c "%a %A %n" /usr/bin/somecommand
```

_exec_
```bash
touch /tmp/su_demo && chmod 4755 /tmp/su_demo && ls -l /tmp/su_demo && stat -c "%a %A" /tmp/su_demo
```

_output_
```bash
-rwsr-xr-x 1 user group 0 Feb 28 10:00 /tmp/su_demo
4755 -rwsr-xr-x
```

Chmod 4755 sets setuid (4) plus standard executable permissions (755). The 's' indicates setuid presence.

- 4755 = setuid(4) + rwxr-xr-x(755)
- Octal notation clearly shows setuid with leading 4
- ls shows 's' in user execute position
- stat shows full 4-digit octal including special bits

**Best practices:**

- Use setuid sparingly and only when necessary
- Never use setuid on shell scripts if possible
- Document why setuid is needed
- Regularly audit files with setuid set
- Prefer sudo/sudoers for permission escalation

**Common errors:**

- **setuid not taking effect**: File must be executable (must have x bit also)
- **Permission issues with setuid scripts**: Use compiled binaries instead of shell scripts for setuid

### Setgid Bit

Understanding and using the setgid special permission

**Keywords:** setgid, sgid, special, 2000, group-id

#### Understanding setgid bit

```bash
# Setgid (Set Group ID) bit = 2000
# When set on executable file:
# - File executes with owner's group permissions
# When set on directory:
# - New files created inherit directory's group, not creator's
# - Enables collaborative directories
# - Shown as 's' in group execute position (rwxr-sr-x)

# In octal notation:
# First digit: 2 = setgid
# chmod 2755 = -rwxr-sr-x (setgid + rwxr-xr-x)
# chmod 2770 = -rwxrws--- (setgid + rwxrwx---)

# Symbolic notation:
# chmod g+s directory/   # add setgid on directory
# chmod g+s file.sh      # add setgid on file

# Use cases:
# - Collaborative directories (inherit group ownership)
# - Shared project folders
# - Group-based permissions
```

_exec_
```bash
mkdir -p /tmp/setgid_test && chmod 2755 /tmp/setgid_test && ls -ld /tmp/setgid_test
```

_output_
```bash
drwxr-sr-x 2 user group 4096 Feb 28 10:00 /tmp/setgid_test
```

The 's' in the group execute position indicates setgid is set on the directory. Files created inherit group ownership.

- Setgid on directory: new files inherit directory's group
- Setgid on file: executes with owner's group
- Shown as 's' in group execute position
- Very useful for collaborative directories

#### Using setgid for collaborative directories

```bash
# Create group-shared directory with setgid
mkdir /home/team/shared
chmod g+w /home/team/shared
chmod g+s /home/team/shared

# Verify new files inherit group
touch /home/team/shared/newfile.txt
ls -l /home/team/shared/newfile.txt
# File will have group ownership of 'team' instead of user's primary group

# Set permissions for collaborative work
chmod 2770 /home/team/shared

# Files created match directory group
chmod g+s directory/    # symbolic method
chmod 2755 directory/   # octal equivalent for rwxr-sr-x
```

_exec_
```bash
mkdir -p /tmp/collab && chmod 2770 /tmp/collab && ls -ld /tmp/collab
```

_output_
```bash
drwxrws--- 2 user group 4096 Feb 28 10:00 /tmp/collab
```

Chmod 2770 sets setgid (2) plus rwxrwx--- (770). Files created inherit directory's group.

- 2770 = setgid(2) + rwxrwx---(770)
- Enables group-based collaboration
- New files automatically group-owned
- Essential for team projects

**Best practices:**

- Use setgid on collaborative directories
- Combine with g+w for shared writable space
- Document shared directory purposes
- Regularly verify group membership

**Common errors:**

- **Files not inheriting group**: Ensure setgid (g+s or 2xxx) is set on directory
- **Group cannot write to directory**: Add g+w with chmod g+w or chmod 2770

### Sticky Bit

Understanding and using the sticky bit special permission

**Keywords:** sticky, sticky-bit, special, 1000, temp

#### Understanding sticky bit

```bash
# Sticky bit = 1000
# When set on directory:
# - Only owner (or root) can delete own files
# - Prevents users from deleting others' files
# - Shown as 't' in other execute position (rwxrwxrwt)
# - NOT valid on regular files (ignored)

# In octal notation:
# First digit: 1 = sticky
# chmod 1777 = rwxrwxrwt (sticky + rwxrwxrwx)
# chmod 1755 = rwxr-xr-t (sticky + rwxr-xr-x)

# Symbolic notation:
# chmod o+t directory/   # add sticky bit on directory
# chmod o-t directory/   # remove sticky bit

# Use cases:
# - /tmp and /var/tmp (prevent users deleting others' files)
# - Shared directories needing file protection
# - Collaborative spaces where only owners delete own files
```

_exec_
```bash
mkdir -p /tmp/sticky_test && chmod 1777 /tmp/sticky_test && ls -ld /tmp/sticky_test
```

_output_
```bash
drwxrwxrwt 2 user group 4096 Feb 28 10:00 /tmp/sticky_test
```

The 't' in the other execute position indicates sticky bit is set. Only file owners can delete their files.

- Sticky bit shown as 't' in other execute position
- Lowercase 't' if execute present, uppercase 'T' if not
- Typically combined with 777 on shared directories
- Essential for shared temp directories

#### Setting and verifying sticky bit

```bash
# Set sticky bit on shared directory
chmod o+t /tmp/shared
chmod 1777 /tmp/shared

# Verify sticky is set
ls -ld /tmp/shared    # look for 't' in position 10
stat /tmp/shared

# View as 4-digit octal
stat -c "%a %A %n" /tmp/shared

# Remove sticky bit
chmod o-t /tmp/shared

# Find directories with sticky bit
find /tmp -perm -1000 -type d

# Compare: with and without sticky
chmod 777 /tmp/test1   # 0777
chmod 1777 /tmp/test2  # 1777 (sticky)
ls -ld /tmp/test1 /tmp/test2
```

_exec_
```bash
mkdir -p /tmp/sticky1 /tmp/sticky2 && chmod 777 /tmp/sticky1 && chmod 1777 /tmp/sticky2
ls -ld /tmp/sticky1 /tmp/sticky2
```

_output_
```bash
drwxrwxrwx 2 user group 4096 Feb 28 10:00 /tmp/sticky1
drwxrwxrwt 2 user group 4096 Feb 28 10:00 /tmp/sticky2
```

First directory (777) shows 'x' in other; second (1777) shows 't'. Only in second can non-owners not delete others' files.

- 1777 = sticky(1) + rwxrwxrwx(777)
- 't' indicates sticky bit protection
- Standard for /tmp directories
- Prevents accidental file deletion

**Best practices:**

- Use sticky on shared temp directories
- Set /tmp and /var/tmp with 1777 and sticky
- Combine with full read/write for visibility
- Document sticky permissions in shared spaces

**Common errors:**

- **Others can still delete files**: Ensure sticky bit (o+t or 1xxx) is set
- **Sticky bit seems ignored**: Sticky only works on directories, not files

## Recursive Operations

Applying chmod recursively to directories and contents

### Recursive Changes

Using -R flag for recursive permission changes

**Keywords:** recursive, recursive-flag, directory-tree, all-contents, capital-r

#### Basic recursive permission changes

```bash
# Recursive chmod with -R flag
# Syntax: chmod -R mode directory

# Apply permissions to all contents of directory
chmod -R 755 /path/to/directory

# Make all files executable recursively
chmod -R u+x /path/to/directory

# Remove write from all files recursively
chmod -R a-w /path/to/directory

# Set permissions for all subdirectories
chmod -R 700 /path/to/private/

# Recursive examples:
chmod -R 644 ./myproject/    # all files 644
chmod -R u+r ./myproject/    # add read for all
chmod -R o-rwx ./myproject/  # remove other access
```

_exec_
```bash
mkdir -p /tmp/recursivetest/{dir1,dir2} && touch /tmp/recursivetest/{file1.txt,dir1/file2.txt,dir2/file3.txt}
chmod -R 644 /tmp/recursivetest && find /tmp/recursivetest -type f -exec ls -l {} \; | awk '{print $1}'
```

_output_
```bash
-rw-r--r--
-rw-r--r--
-rw-r--r--
```

chmod -R 644 applies 644 permissions to all files in the directory tree. All files show -rw-r--r--.

- -R recursively applies to all contents
- Applied to files AND directories
- May result in inaccessible directories (need x for traversal)
- Use with caution on important directories

#### Recursive permission setup for projects

```bash
# Setup project directory structure
# Directories need rwx for access
# Files typically 644, directories 755

# Make all files readable
chmod -R u+r,g+r,o+r ./project/

# Make all files non-writable except owner
chmod -R u-w,g-w,o-w ./project/
chmod -R u+w ./project/

# Make all directories executable
find ./project/ -type d -exec chmod 755 {} \;

# Alternative: single recursive that might lock you out
chmod -R 644 ./project/  # DANGER: directories become inaccessible!

# Better approach: handle files and directories separately
find ./project/ -type f -exec chmod 644 {} \;
find ./project/ -type d -exec chmod 755 {} \;
```

_exec_
```bash
mkdir -p /tmp/proj/{src,docs} && touch /tmp/proj/{README.md,src/main.py,docs/guide.md}
find /tmp/proj -type f -exec chmod 644 {} \;
find /tmp/proj -type d -exec chmod 755 {} \;
find /tmp/proj -type f -o -type d | xargs ls -ld | awk '{print $1, $NF}'
```

_output_
```bash
-rw-r--r-- /tmp/proj/README.md
-rw-r--r-- /tmp/proj/src/main.py
-rw-r--r-- /tmp/proj/docs/guide.md
drwxr-xr-x /tmp/proj
drwxr-xr-x /tmp/proj/src
drwxr-xr-x /tmp/proj/docs
```

Using find with type filter correctly sets files to 644 and directories to 755 separately.

- -R applies to everything; often too broad
- Use find to differentiate files and directories
- Files typically 644, directories 755
- Prevents locking yourself out of directories

**Best practices:**

- Use -R carefully; test on copy first
- Prefer find for fine-grained control
- Set directories to 755+, files to 644+
- Verify with find after recursive chmod
- Use -v to see changes being made

**Common errors:**

- **Cannot access directory after chmod -R 644**: Used find to set directories to 755: find . -type d -exec chmod 755 {} \;
- **Permission denied recursively**: Run as root or ensure you own the directory

### Following Symlinks

Handling symbolic links in recursive operations

**Keywords:** symlink, symbolic-link, recursive, follow-symlinks, -H, -L

#### Understanding symlink permission behavior

```bash
# Basic symlink behavior:
# chmod follows symlinks by default
# Changes the target file, not the symlink

# Symlink permissions are mostly ignored
# Only the target's permissions matter

# Recursive with symlinks:
# -R will follow directory symlinks (DANGER: can create loops!)
# Use -H flag to avoid following symlinks
# Use -L flag to follow all symlinks

# Examples:
chmod -R 755 /path/  # may follow symlinks
chmod -H 755 /path/  # don't follow symlinks

# Check symlink status
ls -l file_link    # shows -> target

# Change target through symlink
chmod 600 file_link  # changes target, not symlink
```

_exec_
```bash
touch /tmp/target.txt && ln -s /tmp/target.txt /tmp/link_to_target
chmod 644 /tmp/target.txt && ls -l /tmp/target.txt /tmp/link_to_target
```

_output_
```bash
-rw-r--r-- 1 user group 0 Feb 28 10:00 /tmp/target.txt
lrwxrwxrwx 1 user group 15 Feb 28 10:00 /tmp/link_to_target -> /tmp/target.txt
```

Symlink shows lrwxrwxrwx (always 777). The target file shows actual permissions.

- Symlinks always show 777 permissions
- Changing permissions through symlink changes target
- Symlink permissions cannot be changed on most systems
- Recursive follows symlinks (potential infinite loop risk)

#### Avoiding symlink issues in recursive operations

```bash
# Option 1: Skip symlinks entirely
find /path -type f -not -type l -exec chmod 644 {} \;

# Option 2: Use find with maxdepth to avoid deep recursion
find /path -maxdepth 3 -type f -exec chmod 644 {} \;

# Option 3: List symlinks before recursive operation
find /path -type l -o -type L

# Typical safe approach:
# Use find to exclude symlinks
find /path -type f ! -type l -exec chmod 644 {} \;
find /path -type d ! -type l -exec chmod 755 {} \;

# Alternative: using ls to identify symlinks
ls -la /path | grep "^l"
```

_exec_
```bash
mkdir -p /tmp/safe_test && touch /tmp/safe_test/file.txt && ln -s /tmp/safe_test/file.txt /tmp/safe_test/link.txt
find /tmp/safe_test -type f -not -type l -exec chmod 644 {} \;
ls -la /tmp/safe_test/
```

_output_
```bash
total 8
-rw-r--r-- 1 user group 0 Feb 28 10:00 file.txt
lrwxrwxrwx 1 user group 15 Feb 28 10:00 link.txt -> /tmp/safe_test/file.txt
```

Using find with -not -type l excludes symlinks from the operation. Regular file is chmod'd, symlinks unchanged.

- find -not -type l excludes symlinks
- Prevents accidental modifications through symlinks
- Safe approach for recursive operations
- Recommended for production scripts

**Best practices:**

- Use find with type filters instead of -R for safety
- Exclude symlinks when doing recursive changes
- Test on test directory structure first
- Avoid -L flag unless you understand implications
- Document why you're following/skipping symlinks

**Common errors:**

- **Infinite loop with recursive symlinks**: Use find with -not -type l to exclude symlinks
- **Changed permissions on symlink instead of target**: Remember chmod follows symlinks; target gets changed

### Recursive with Options

Combining recursive with verbose and other options

**Keywords:** recursive, verbose, options, changes, quiet, combined-flags

#### Verbose recursive operations

```bash
# -R: Recursive (required)
# -v: Verbose (show all changes)
# -c: Changes only (show only changed items)
# -f: Force/quiet (suppress errors)

# Common combinations:
# chmod -R -v 755 dir/   # recursive + verbose
# chmod -Rv 755 dir/     # combined flags (same as above)
# chmod -Rc 755 dir/     # recursive + changes only

# Examples:
chmod -Rv 644 ./myfiles/         # show all changes
chmod -Rc 755 ./project/         # show only what changed
chmod -Rf 755 ./dir/             # force, suppress errors
chmod -Rvc 644 ./src/ | head -20 # verbose + limit output
```

_exec_
```bash
mkdir -p /tmp/verb_test && touch /tmp/verb_test/{f1.txt,f2.txt,f3.txt}
chmod -Rc 644 /tmp/verb_test 2>&1 | head -5
```

_output_
```bash
mode of '/tmp/verb_test/f1.txt' changed from 0644 to 0644
```

Chmod -Rc shows only items that were actually changed. With -v, all items would be listed.

- -Rv shows all files processed
- -Rc shows only files that had permission changes
- -Rf suppresses error messages
- Useful for scripts and large operations

#### Tracking recursive changes with verbose and logging

```bash
# Log all changes made
chmod -Rv 755 /path/to/dir > chmod_log.txt 2>&1

# Count changes made
chmod -Rc 644 /path/to/dir | wc -l

# Show changes with timestamps
date && chmod -Rc 755 /path/to/dir && date

# Audit changes after recursive chmod
chmod -Rc 700 /path/ > changes.log
cat changes.log | head -20
cat changes.log | tail -5

# Compare sizes before and after
du -sh /path/before && chmod -R 755 /path/ && du -sh /path/after
```

_exec_
```bash
mkdir -p /tmp/log_test && touch /tmp/log_test/{a,b,c}.txt
chmod -Rc 755 /tmp/log_test 2>&1 | head -3
```

_output_
```bash
mode of '/tmp/log_test/a.txt' changed from 0644 to 0755
mode of '/tmp/log_test/b.txt' changed from 0644 to 0755
mode of '/tmp/log_test/c.txt' changed from 0644 to 0755
```

-Rc lists only items with actual permission changes. Output can be captured for audit trails.

- -Rc useful for audit logging
- Can redirect output to file for documentation
- Combine with wc -l to count changes
- Good for tracking configuration changes

**Best practices:**

- Use -Rc for production changes to see what changed
- Use -Rv for debugging to see all operations
- Log output with > filename for audit trails
- Test with small directories first
- Use -f to suppress errors in automation

**Common errors:**

- **Too much output from -v**: Use -Rc to show only changes or pipe to head/tail
- **Changes not visible**: Use -Rc; -c only shows items that actually changed

## Advanced Usage

Advanced chmod techniques and options

### Reference Mode

Using --reference flag to copy permissions from another file

**Keywords:** reference, copy-permissions, same-as, reference-flag, template

#### Copy permissions from reference file

```bash
# Copy permissions from one file to another
# Syntax: chmod --reference=source_file target_file

# Examples:
chmod --reference=/etc/passwd /tmp/myconf
chmod --reference=template.txt *.txt

# Use cases:
# - Match file permissions to template
# - Standardize permissions across files
# - Copy permissions without knowing exact mode

# Combined with find:
find . -name "*.log" -exec chmod --reference=template.log {} \;

# Verify same permissions
stat -c "%a %A" template.txt
stat -c "%a %A" newfile.txt
```

_exec_
```bash
touch /tmp/template && touch /tmp/testfile && chmod 650 /tmp/template
chmod --reference=/tmp/template /tmp/testfile
echo "Template: $(ls -l /tmp/template | awk '{print $1}')"
echo "File:     $(ls -l /tmp/testfile | awk '{print $1}')"
```

_output_
```bash
Template: -rw-r-x---
File:     -rw-r-x---
```

chmod --reference copies exact permissions from template to target file without specifying numeric mode.

- Useful for matching permissions across files
- No need to know exact permissions of reference
- Template file must exist and be accessible
- Works with any file permissions

#### Batch applying template permissions with reference

```bash
# Create template file with desired permissions
touch standard_template
chmod 644 standard_template

# Apply to all files in directory
for file in *.txt; do
  chmod --reference=standard_template "$file"
done

# Using find to apply template
find . -type f -name "*.log" -exec chmod --reference=/etc/syslog.conf {} \;

# Verify all have same permissions
find . -type f -exec ls -l {} \; | awk '{print $1}' | sort | uniq
```

_exec_
```bash
mkdir -p /tmp/batch_ref && touch /tmp/batch_ref/template /tmp/batch_ref/{f1,f2,f3}.txt
chmod 700 /tmp/batch_ref/template
for f in /tmp/batch_ref/*.txt; do chmod --reference=/tmp/batch_ref/template "$f"; done
ls -l /tmp/batch_ref/*.txt | awk '{print $1}'
```

_output_
```bash
-rwx------
-rwx------
-rwx------
```

Using chmod --reference in a loop applies template permissions to multiple files efficiently.

- Useful for batch operations
- Template-based consistency
- Works with find and loops
- No need to calculate modes manually

**Best practices:**

- Create explicit template files for standard permissions
- Use --reference for consistency
- Document template files and their purposes
- Verify template permissions before batch applying

**Common errors:**

- **Reference file not found**: Ensure --reference path is correct and file exists
- **Permissions not copied**: Check template file is readable and accessible

### Logical Operators

Understanding logical operators in permission expressions

**Keywords:** logical, comma, chaining, expressions, combining

#### Combining permissions with logical operators

```bash
# Comma-separated list of changes all applied
# chmod u+rwx,g+rx,o-rwx file

# All changes are processed in sequence
# Each builds on previous result

# Examples:
chmod u+rw,g+r,o=r file.txt       # set specific perms
chmod a+r,u+w file.txt            # add read all, add write user
chmod u-w,g-w,o-w file.txt        # remove write from all
chmod u=rwx,g=rx,o= directory/    # set 750 permissions

# Order matters for clarity, usually:
# 1. User changes
# 2. Group changes
# 3. Other changes
```

_exec_
```bash
touch /tmp/logic_test && chmod 000 /tmp/logic_test
chmod u+rw,g+r,o= /tmp/logic_test && ls -l /tmp/logic_test | awk '{print $1}'
```

_output_
```bash
-rw-r-----
```

Multiple changes with commas are applied sequentially. Result is rw-r-----  (640 permissions).

- Comma separates multiple changes
- No spaces around comma
- Changes applied left to right
- Each change builds on previous result

#### Complex permission expressions

```bash
# Build complex permissions in single command
chmod u=rwx,g=rx,o= script.sh          # 750: user full, group rx, other none

# Add and remove in same command
chmod a+r,a-x file.txt                  # add read all, remove execute all

# Different operations for different users
chmod u+w,g-w,o-rwx file.txt            # user add write, group rem write, other none

# Combining with special bits
chmod u+rws,g+rx,o= program.sh          # setuid + rwx for user, rx for group

# Security hardening in one command
chmod u-x,g-rwx,o-rwx file.txt          # remove execute user, all from group/other
```

_exec_
```bash
touch /tmp/complex && chmod 777 /tmp/complex
chmod u+rws,g+r,o= /tmp/complex && ls -l /tmp/complex | awk '{print $1}'
```

_output_
```bash
-rwsr-----
```

Complex expression sets user with setuid+rwx, group read, other nothing. Resulting in 4540.

- Multiple operations enable complex setups
- Setuid/setgid/sticky in complex expressions
- Single command atomic operation
- More readable than octal for complex requirements

**Best practices:**

- Keep expressions readable with logical grouping
- Test complex expressions on test files
- Document complex permission changes
- Verify result with ls -l

**Common errors:**

- **Unexpected permission result**: Remember order of operations; test each step
- **Syntax error with multiple changes**: Use commas without spaces: u+x,g+x not u+x, g+x

### Batch Operations

Performing chmod on multiple files efficiently

**Keywords:** batch, multiple, find, xargs, loop

#### Batch chmod using find and xargs

```bash
# Using find to locate and chmod files
find /path -type f -exec chmod 644 {} \;

# Using find with xargs (more efficient)
find /path -type f -print0 | xargs -0 chmod 644

# Separate files and directories
find /path -type f -exec chmod 644 {} \;
find /path -type d -exec chmod 755 {} \;

# Limited depth search
find /path -maxdepth 2 -type f -exec chmod 644 {} \;

# Specific file patterns
find /path -name "*.txt" -exec chmod 644 {} \;
find /path -name "*.sh" -exec chmod 755 {} \;
```

_exec_
```bash
mkdir -p /tmp/batch && touch /tmp/batch/{a.txt,b.txt,c.py}
find /tmp/batch -name "*.txt" -exec chmod 600 {} \;
ls -l /tmp/batch | awk '{print $1, $NF}'
```

_output_
```bash
total 0
-rw------- a.txt
-rw------- b.txt
-rw-r--r-- c.py
```

find selects only *.txt files and chmod applies 600 to them. c.py remains unchanged.

- find is precise for selecting files
- -exec runs chmod on each found file
- xargs is more efficient for large lists
- maxdepth prevents deep recursion if desired

#### Advanced batch operations with patterns

```bash
# Apply different permissions based on file types
find . -type f -name "*.sh" -exec chmod 755 {} \;
find . -type f -name "*.py" -exec chmod 755 {} \;
find . -type f -name "*.conf" -exec chmod 640 {} \;

# Batch operations with conditions
find . -type f -size +1M -exec chmod 444 {} \;  # large files read-only

# Complex find with chmod
find . -perm 777 -exec chmod 755 {} \;          # change overly permissive

# Using -newer for recent files
find . -type f -newer lastmod -exec chmod 644 {} \;

# Batch with progress reporting
find . -type f | wc -l                          # count first
find . -type f -print0 | xargs -0 chmod 644
```

_exec_
```bash
mkdir -p /tmp/advanced_batch && touch /tmp/advanced_batch/{script.sh,config.conf,data.txt}
chmod 777 /tmp/advanced_batch/*
find /tmp/advanced_batch -name "*.sh" -exec chmod 755 {} \;
find /tmp/advanced_batch -name "*.conf" -exec chmod 640 {} \;
ls -l /tmp/advanced_batch | awk '{print $1, $NF}'
```

_output_
```bash
total 0
-rw-r----- config.conf
-rw-r--r-- data.txt
-rwxr-xr-x script.sh
```

Different file types get different permissions using separate find commands with name patterns.

- Chaining find commands handles different file types
- Efficient for maintaining consistent permissions
- Can add conditions for selective application
- Scripts/binaries get 755, configs 640, data 644

**Best practices:**

- Use find -print0 with xargs -0 for whitespace safety
- Separate files and directories
- Test on small sets before large batch operations
- Document batch operations in scripts/comments

**Common errors:**

- **File with spaces not found**: Use -print0 with xargs -0 for safe handling
- **Batch operation too slow**: Use xargs instead of -exec for efficiency

## Practical Examples

Real-world chmod scenarios and practical use cases

### Real-World Scenarios

Common practical chmod use cases

**Keywords:** real-world, scenarios, web, ssh, configuration, practical

#### Securing SSH key files

```bash
# SSH keys must be private and non-world-readable
chmod 600 ~/.ssh/id_rsa           # private key readable only by owner
chmod 644 ~/.ssh/id_rsa.pub       # public key can be read by anyone
chmod 700 ~/.ssh/                 # SSH directory owner only

# Set correct permissions on new SSH directory
mkdir ~/.ssh
chmod 700 ~/.ssh

# Keys from others must be protected
chmod 600 ~/.ssh/authorized_keys  # control access to account

# Fix common SSH permission issues
chmod 755 ~/                       # home directory accessible
chmod 700 ~/.ssh                   # SSH directory private
chmod 600 ~/.ssh/id_rsa           # private key secure
```

_exec_
```bash
mkdir -p /tmp/ssh_test/.ssh && touch /tmp/ssh_test/.ssh/{id_rsa,id_rsa.pub}
chmod 700 /tmp/ssh_test/.ssh && chmod 600 /tmp/ssh_test/.ssh/id_rsa && chmod 644 /tmp/ssh_test/.ssh/id_rsa.pub
ls -la /tmp/ssh_test/.ssh/
```

_output_
```bash
total 8
drwx------ 2 user group 4096 Feb 28 10:00 .
dr-xr-xr-x 3 user group 4096 Feb 28 10:00 ..
-rw------- 1 user group 0 Feb 28 10:00 id_rsa
-rw-r--r-- 1 user group 0 Feb 28 10:00 id_rsa.pub
```

SSH keys require specific permissions: directory 700, private key 600, public key 644. Essential for SSH security.

- SSH refuses if .ssh is not 700
- Private keys must be 600
- Public keys can be 644
- Home directory typically 755
- Critical for security

#### Web server file permissions

```bash
# Web server files and directories
# htdocs/html files readable by everyone, writable only by owner
chmod 644 /var/www/html/*.html    # HTML files
chmod 644 /var/www/html/*.css     # CSS files
chmod 644 /var/www/html/*.js      # JavaScript
chmod 755 /var/www/html/          # directory must be traversable

# Server-side scripts (PHP, Python, etc.)
chmod 644 /var/www/html/*.php     # script file readable by server
chmod 644 /var/www/cgi-bin/*      # CGI scripts

# Upload directories (writable by server)
chmod 755 /var/www/html/uploads/  # directory writable
chmod 755 /var/www/html/tmp/      # temp directory

# Configuration files (private)
chmod 600 /var/www/html/config.php      # config secure
chmod 600 /var/www/html/.env            # environment file
```

_exec_
```bash
mkdir -p /tmp/webroot && touch /tmp/webroot/{index.html,style.css,config.php}
chmod 755 /tmp/webroot && chmod 644 /tmp/webroot/{index.html,style.css} && chmod 600 /tmp/webroot/config.php
ls -la /tmp/webroot/ | tail -+4 | awk '{print $1, $NF}'
```

_output_
```bash
-rw-r--r-- config.php
-rw-r--r-- index.html
-rw-r--r-- style.css
```

Web files typically use 644 (readable by all, writable by owner) with 755 directories for traversal.

- HTML/CSS/JS files: 644
- Directories: 755
- Config files: 600
- Owner must be restorable (usually root or app user)

#### Configuration and system files

```bash
# System configuration files
chmod 644 /etc/passwd                     # readable by all, root write
chmod 640 /etc/shadow                     # readable by root/group only
chmod 644 /etc/hosts                      # readable by all
chmod 644 /etc/hostname                   # readable by all

# System scripts and binaries
chmod 755 /usr/local/bin/myscript         # executable by all
chmod 755 /etc/init.d/myservice           # service script executable

# Log files
chmod 640 /var/log/myapp.log              # readable by owner/group
chmod 755 /var/log/                       # directory traversable

# Application data files
chmod 640 /var/lib/myapp/database.db      # readable by app
chmod 750 /var/lib/myapp/                 # directory for group access
```

_exec_
```bash
mkdir -p /tmp/sysconfig && touch /tmp/sysconfig/{config.ini,script.sh,app.log}
chmod 644 /tmp/sysconfig/config.ini && chmod 755 /tmp/sysconfig/script.sh && chmod 640 /tmp/sysconfig/app.log
ls -l /tmp/sysconfig | tail -+4 | awk '{print $1, $NF}'
```

_output_
```bash
-rw-r----- app.log
-rw-r--r-- config.ini
-rwxr-xr-x script.sh
```

Configuration files (644), executables (755), and logs (640-650) have different permission requirements.

- Config files typically 644 or 640
- Scripts/binaries 755
- Log files 640-650
- Sensitive files 600

**Best practices:**

- [object Object]
- SSH keys require 600 and 700
- Regularly audit permissions in production
- Document permission requirements

**Common errors:**

- **SSH key permission too open**: Set to 600 and .ssh directory to 700
- **Web files not accessible**: Ensure directories are 755 and files 644+

### Security Best Practices

Security implications and best practices for file permissions

**Keywords:** security, best-practices, vulnerability, exposure, least-privilege

#### Principle of least privilege

```bash
# Use minimum permissions necessary
# Start restrictive, add permissions as needed

# Private files: start with 600
chmod 600 sensitive.txt      # only owner can read/write

# Read-only files: use 444
chmod 444 readonly.conf      # no one can modify

# Executable only by owner: use 700
chmod 700 admin-only.sh      # only owner can execute

# Shared group files: use 640 not 644
chmod 640 shared.log         # group can read, others cannot

# Public files: use 644 minimum
chmod 644 public.html        # all can read, none can write

# Never use 777 or 666
# Avoid: chmod 777 file.txt    # INSECURE: all can do everything
# Avoid: chmod 666 file.txt    # INSECURE: all can modify

# Audit tool:
# Find overly permissive files
find / -perm -002 -type f    # world-writable
find / -perm -020 -type f    # group-writable
```

_exec_
```bash
touch /tmp/sec_test && chmod 600 /tmp/sec_test
echo "=== Secure (600) ===" && ls -l /tmp/sec_test
chmod 666 /tmp/sec_test 2>/dev/null || true
echo "=== Insecure (666) ===" && ls -l /tmp/sec_test
```

_output_
```bash
=== Secure (600) ===
-rw------- 1 user group 0 Feb 28 10:00 /tmp/sec_test
=== Insecure (666) ===
-rw-rw-rw- 1 user group 0 Feb 28 10:00 /tmp/sec_test
```

Secure permissions (600) restrict to owner only. Insecure (666) allows anyone to modify the file.

- 600 is secure, 644 for public reading
- 666 is dangerous for any file
- 777 very rarely justified
- Audit regularly for over-permissive files

#### Preventing common security mistakes

```bash
# WRONG: Making config world-readable
# chmod 644 /etc/myapp/db.conf    # database password exposed!

# RIGHT: Keep config private
chmod 600 /etc/myapp/db.conf      # only application can read

# WRONG: Making .ssh directory accessible
# chmod 755 ~/.ssh                 # allows SSH hijacking!

# RIGHT: Keep SSH directory private
chmod 700 ~/.ssh                   # only owner can access

# WRONG: Making shell scripts world-writable
# chmod 777 /usr/local/bin/script  # anyone can modify!

# RIGHT: Script executable but not modifiable
chmod 755 /usr/local/bin/script    # all can execute, owner writes

# WRONG: Making sensitive data world-readable
# chmod 644 ~/.aws/credentials     # exposes AWS access!

# RIGHT: Keep credentials private
chmod 600 ~/.aws/credentials       # only owner can read

# Audit for problems:
find ~ -perm -0077              # files with group/other access
find ~ -type f -perm /022       # group/other writable
```

_exec_
```bash
touch /tmp/mistake && chmod 666 /tmp/mistake 2>&1 | head -1 || chmod 644 /tmp/mistake
echo "Insecure: $(ls -l /tmp/mistake | awk '{print $1}')"
chmod 600 /tmp/mistake
echo "Secure:   $(ls -l /tmp/mistake | awk '{print $1}')"
```

_output_
```bash
Insecure: -rw-r--r--
Secure:   -rw-------
```

Security improves from 644 (world-readable) to 600 (owner-only). Sensitive data must be 600.

- Database configs: 600
- SSH directories: 700, keys: 600
- Credentials: 600
- Regular audit prevents exposure

**Best practices:**

- Start with restrictive, add permissions as needed
- Never use 777 unless absolutely justified
- Never use 666 for any file
- Keep sensitive .600 or 700
- Regularly audit permissions

**Common errors:**

- **Exposing configuration/credentials**: Always use 600 for sensitive files
- **SSH access compromised**: Ensure .ssh is 700 and keys are 600
