Skip to main content
Ctrl+K

Think Bash

  • Think Bash

The Shell and the System

  • 1. Terminal & System
    • 1.1. Unix History & Design
    • 1.2. Terminal Navigation
    • 1.3. Kernel & Shell
    • 1.4. Filesystem Hierarchy
    • 1.5. Lab: Exploring Your System
  • 2. Filesystem Essentials
    • 2.1. Advanced Navigation
    • 2.2. File Management
    • 2.3. File Attributes & Links
    • 2.4. Hidden Files & Config
    • 2.5. Project Organization
    • 2.6. Lab: Filesystem Practice
  • 3. Permissions & Access
    • 3.1. Users, Groups & Privileges
    • 3.2. Permission Symbols
    • 3.3. Umask & Defaults
    • 3.4. Environment Variables
    • 3.5. Lab: Permissions Management
  • 4. Unix Utilities
    • 4.1. Everything Is A File
    • 4.2. Viewing Data
    • 4.3. Searching & Filtering
    • 4.4. Data Tools
    • 4.5. Pipes & Redirection
    • 4.6. Lab: Text Pipeline Analysis

Bash Programming

  • 5. Bash Syntax & Variables
    • 5.1. Syntax & Quoting
    • 5.2. Variables & Expansion
    • 5.3. Parameter Substitution
    • 5.4. Arithmetic and String Operations
    • 5.5. Lab: Bash Variables and Operations
  • 6. Operators
    • 6.1. Arithmetic
    • 6.2. Comparison & Logic
    • 6.3. String & File Tests
    • 6.4. Expressions in Conditionals
    • 6.5. Lab: Operator Practice
  • 7. Control Flow
    • 7.1. if/elif/else and case Statements
    • 7.2. Loops: for, while, and until
    • 7.3. Loop Control: break and continue
    • 7.4. User Input & Arguments
    • 7.5. Lab: Automation Scripts
  • 8. Functions & Modularity
    • 8.1. Defining Functions
    • 8.2. Local vs Global
    • 8.3. Return Values
    • 8.4. Function Libraries
    • 8.5. Lab: Modular Scripting
  • 9. Text Processing
    • 9.1. Standard Streams and File Descriptors
    • 9.2. Advanced Redirection
    • 9.3. awk & sed
    • 9.4. Generating Reports
    • 9.5. Lab: Parsing Structured Data

System Interaction

  • 10. Processes
    • 10.1. Process Management
    • 10.2. Job Control
    • 10.3. Memory & Disk
    • 10.4. Process Monitoring & Performance
    • 10.5. Lab: System Monitoring
  • 11. Error Handling
    • 11.1. Exit Codes
    • 11.2. Options & Traps for Error Handling
    • 11.3. Defensive Scripting
    • 11.4. Logging & Errors
    • 11.5. Lab: Debugging
  • 12. Scheduling
    • 12.1. Cron & At
    • 12.2. Maintenance & Backup
    • 12.3. Long-Running Tasks
    • 12.4. Parallel Processing and Performance
    • 12.5. Lab: Automated Reporting
  • 13. Networking
    • 13.1. Network Commands: Ping, Curl, and Wget
    • 13.2. Secure File Transfer: SCP and Rsync
    • 13.3. Remote Execution with SSH
    • 13.4. Network Automation
    • 13.5. Lab: Remote Sync & Networking

Advanced Topics

  • 14. Arrays & Config
    • 14.1. Arrays
    • 14.2. Here-Documents
    • 14.3. Shell Options and Subshells
    • 14.4. Startup Files
    • 14.5. Lab: Configuration & Data Structures
  • 15. Capstone Project
    • 15.1. 15.2 Project Design and Planning
    • 15.2. 15.3 Scripts, Logs & Alerts
    • 15.3. 15.4 Testing and Debugging the Project
    • 15.4. 15.5 Packaging and Version Control
    • 15.5. 15.6 Capstone Reflection

Appendices

  • A: Bash Cheat Sheet
  • B: Debugging Guide
  • C: POSIX vs Bash
  • D: Security
  • E: Further Reading
  • F: Version Control
  • .ipynb

File Attributes & Links

Contents

  • 2.3.1. File Types
    • 2.3.1.1. Identifying File Types
  • 2.3.2. File Permissions Deep Dive
    • 2.3.2.1. Permission Values
    • 2.3.2.2. Octal Notation
    • 2.3.2.3. Recursive Permissions
    • 2.3.2.4. Special Permissions
  • 2.3.3. Hard Links vs Symbolic Links
    • 2.3.3.1. Hard Links
    • 2.3.3.2. Symbolic Links (Symlinks)
    • 2.3.3.3. Practical Examples
    • 2.3.3.4. Link Troubleshooting
  • 2.3.4. File Metadata
    • 2.3.4.1. Understanding the Timestamps
    • 2.3.4.2. Finding Files by Attributes
  • 2.3.5. Ownership Management
    • 2.3.5.1. Practical Example: Setting Up a Shared Project

2.3. File Attributes & Links#

Files have metadata (attributes) beyond just content. Understanding these attributes and the different ways to link files is essential for effective filesystem management.

2.3.1. File Types#

Linux treats everything as a file. The first character in ls -l output indicates the file type:

$ ls -l /dev/
crw-rw----  1 root  tty   5, 0 Jan 10 14:23 tty
lrwxrwxrwx  1 root  root  13 Jan  9 08:15 stdout -> /proc/self/fd/1
brw-rw----  1 root  disk  8, 0 Jan 10 14:00 sda

Character

Type

Example

-

Regular file

text files, binaries

d

Directory

folders

l

Symbolic link

shortcuts

c

Character device

/dev/tty, /dev/null

b

Block device

/dev/sda, /dev/sdb

p

Named pipe

inter-process communication

s

Socket

/var/run/docker.sock

2.3.1.1. Identifying File Types#

# Show file type
$ file /etc/passwd
/etc/passwd: ASCII text

$ file /usr/bin/bash
/usr/bin/bash: ELF 64-bit LSB executable

$ file /dev/null
/dev/null: character special (1/3)

2.3.2. File Permissions Deep Dive#

Understanding permissions requires breaking down the 9-character string:

rwxr-xr-x
│││││││││
│││││││││
│││├─┤├─┤└─ Others (world)
│││├─┤└────── Group
│││└────────── Owner (user)
└┴┴─ Permissions (read, write, execute)

2.3.2.1. Permission Values#

Permission

File

Directory

r (read, 4)

View contents

List files in it

w (write, 2)

Modify contents

Create/delete files in it

x (execute, 1)

Run as program

Enter/access it

2.3.2.2. Octal Notation#

# rwx = 4+2+1 = 7
# r-x = 4+0+1 = 5
# r-- = 4+0+0 = 4
# --- = 0+0+0 = 0

$ chmod 755 script.sh   # rwxr-xr-x (user full, others execute)
$ chmod 644 data.txt    # rw-r--r-- (user write, others read)
$ chmod 700 private/    # rwx------ (user full, others no access)

2.3.2.3. Recursive Permissions#

# Change permissions on directory and contents
$ chmod -R 755 ~/myproject/

# Apply different permissions to files vs directories
$ find ~/myproject -type f -exec chmod 644 {} \;
$ find ~/myproject -type d -exec chmod 755 {} \;

2.3.2.4. Special Permissions#

# Sticky bit (only owner can delete): chmod 1777 dir/
# SetUID (run as file owner): chmod 4755 binary
# SetGID (run as file group): chmod 2755 binary

$ ls -l /tmp
drwxrwxrwt 10 root root 4096 Jan 10 14:45 /tmp  # 't' = sticky bit

2.3.3. Hard Links vs Symbolic Links#

Both create multiple names for files, but work very differently.

2.3.3.1. Hard Links#

A hard link is another name for the same inode:

# Create a hard link
$ ln original.txt hardlink.txt

# Both point to the same inode (same file)
$ ls -i
1048576 original.txt
1048576 hardlink.txt

# Edit either file, both change (it's the same content)
$ echo "new content" > original.txt
$ cat hardlink.txt
new content

# Delete original, hardlink still works
$ rm original.txt
$ cat hardlink.txt
new content  # Still accessible!

# Delete both to remove the file
$ rm hardlink.txt  # Now file is truly deleted

Hard Link Limitations:

  • Can’t link to directories (creates filesystem cycles)

  • Can’t link across filesystems

  • Invisible to users (no indication which is “original”)

Use cases: Backups that save space, ensuring file survives deletion

2.3.3.2. Symbolic Links (Symlinks)#

A symbolic link is a reference (like a shortcut):

# Create a symlink
$ ln -s /full/path/to/original.txt symlink.txt

# Different inodes (different files)
$ ls -i
1048576 original.txt
1048577 symlink.txt -> original.txt

# Symlink points to path, not data
$ cat symlink.txt  # Works (follows the link)
content of original

# Delete original, symlink breaks
$ rm original.txt
$ cat symlink.txt
cat: symlink.txt: No such file or directory  # Broken link

# But symlink still exists (broken)
$ ls -l symlink.txt
lrwxrwxrwx 1 user group 11 Jan 10 symlink.txt -> original.txt

Advantages over hard links:

  • Works for directories

  • Works across filesystems

  • Can link to non-existent paths

  • Obviously a link (you can see it)

Use cases: Creating aliases, organizing related files, version management

2.3.3.3. Practical Examples#

# Version management
$ ln -s app-v2.0.jar app.jar  # Point to current version
$ ln -s app-v3.0.jar app.jar  # Update by changing symlink

# Organize code
$ ln -s ~/repos/project/src src  # Reference nested code from home

# Link configuration
$ ln -s ~/.config/dotfiles/.bashrc ~/.bashrc  # Managed from repo

# Check for broken symlinks
$ find ~ -type l ! -exec test -e {} \; -print

2.3.3.4. Link Troubleshooting#

# Verify symlink target
$ readlink ~/mylink
/full/path/to/target

# Get full path
$ readlink -f ~/mylink
/full/resolved/path/target

# Count hard links (number after permissions)
$ ls -l original.txt
-rw-r--r-- 3 user group 100 Jan 10  # 3 hard links exist

2.3.4. File Metadata#

Files carry more information than just permissions:

# Full details with stat command
$ stat /etc/passwd
  File: /etc/passwd
  Size: 2156       Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1049827    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-01-10 14:30:45.123456789 -0500
Modify: 2024-01-10 12:15:32.987654321 -0500
Change: 2024-01-10 12:15:32.987654321 -0500

2.3.4.1. Understanding the Timestamps#

  • Access (atime): Last time file was read

  • Modify (mtime): Last time file contents changed

  • Change (ctime): Last time metadata (permissions, owner) changed

2.3.4.2. Finding Files by Attributes#

# Files modified in last 7 days
$ find ~ -type f -mtime -7

# Files accessed more than 30 days ago (for cleanup)
$ find ~ -type f -atime +30

# Files exactly 1 minute old
$ find ~ -type f -mmin -1

# Large files (over 100MB)
$ find / -type f -size +100M

# Empty files
$ find ~ -type f -empty

# By ownership
$ find ~ -type f -user $USER
$ find ~ -type f -group admin

2.3.5. Ownership Management#

Controlling who owns files:

# Change owner (requires sudo)
$ sudo chown newuser file.txt

# Change group
$ chgrp developers file.txt

# Change both at once
$ sudo chown user:group file.txt

# Recursive change
$ sudo chown -R user:group ~/myproject/

# Using reference file
$ chown --reference=original.txt copy.txt  # Same owner as original

2.3.5.1. Practical Example: Setting Up a Shared Project#

$ mkdir ~/team-project
$ chgrp team ~/team-project
$ chmod 770 ~/team-project         # rwx for user and group
$ chmod g+s ~/team-project        # New files inherit group

# Now all files created inherit 'team' group ownership
$ touch ~/team-project/file.txt
$ ls -l ~/team-project/file.txt
-rw-r--r-- 1 user team 0 Jan 10 file.txt

previous

2.2. File Management

next

2.4. Hidden Files & Config

Contents
  • 2.3.1. File Types
    • 2.3.1.1. Identifying File Types
  • 2.3.2. File Permissions Deep Dive
    • 2.3.2.1. Permission Values
    • 2.3.2.2. Octal Notation
    • 2.3.2.3. Recursive Permissions
    • 2.3.2.4. Special Permissions
  • 2.3.3. Hard Links vs Symbolic Links
    • 2.3.3.1. Hard Links
    • 2.3.3.2. Symbolic Links (Symlinks)
    • 2.3.3.3. Practical Examples
    • 2.3.3.4. Link Troubleshooting
  • 2.3.4. File Metadata
    • 2.3.4.1. Understanding the Timestamps
    • 2.3.4.2. Finding Files by Attributes
  • 2.3.5. Ownership Management
    • 2.3.5.1. Practical Example: Setting Up a Shared Project

By Tsangyao Chen

© Copyright 2025.