跳转至

文件与目录管理

文件与目录管理

📌 学习时间:3-4天 📌 难度级别:⭐⭐ 基础 📌 前置知识:Linux基础入门


📚 章节概述

文件与目录管理是 Linux 最核心的操作技能。本章将全面介绍文件操作命令、权限管理体系(包括特殊权限 SUID/SGID/Sticky)、ACL 访问控制列表、硬链接与软链接、通配符模式匹配等,配合大量实操示例,帮助你真正掌握 Linux 文件管理。

🎯 学习目标

  • 熟练使用文件与目录操作命令(ls/cd/mkdir/rm/cp/mv)
  • 掌握文件查找工具(find/locate/which/whereis)
  • 深入理解文件权限体系(rwx/chmod/chown/chgrp)
  • 掌握特殊权限(SUID/SGID/Sticky Bit)
  • 了解 ACL 扩展权限
  • 理解硬链接与软链接的区别和应用场景
  • 熟练使用通配符进行文件匹配

📖 1. 路径与目录导航

1.1 绝对路径与相对路径

Bash
# 绝对路径:从根目录 / 开始的完整路径
/home/alice/Documents/report.txt
/etc/nginx/nginx.conf

# 相对路径:相对于当前目录的路径
./report.txt          # 当前目录下的文件(./ 可省略)
../config/app.conf    # 上级目录的 config 下
../../shared/data     # 上两级目录的 shared 下

# 特殊路径符号
.     当前目录
..    上一级目录
~     当前用户家目录
~bob  用户 bob 的家目录
-     上一次所在目录

1.2 目录导航命令

Bash
# cd - 切换目录(Change Directory)
cd /etc                      # 切换到 /etc 目录
cd ~                         # 回到家目录
cd                           # 回到家目录(省略参数)
cd ..                        # 返回上级目录
cd -                         # 切换到上一次的目录
cd ~/Documents               # 切换到家目录下的 Documents

# pwd - 显示当前工作目录(Print Working Directory)
pwd                          # /home/alice/Documents
pwd -P                       # 显示真实路径(解析符号链接)

# pushd / popd - 目录栈(重要的高效技巧)
pushd /var/log               # 切换到 /var/log,并将当前目录压入栈
pushd /etc/nginx             # 切换到 /etc/nginx,压入栈
dirs                         # 查看目录栈
popd                         # 弹出栈顶,返回 /var/log
popd                         # 弹出栈顶,返回原始目录

📖 2. 文件与目录基本操作

2.1 查看文件列表 - ls

Bash
# ls - 列出目录内容(List)
ls                           # 列出当前目录
ls /etc                      # 列出 /etc 目录
ls -l                        # 长格式显示(权限、大小、时间等)
ls -a                        # 显示隐藏文件(以.开头的文件)
ls -la                       # 长格式 + 隐藏文件
ls -lh                       # 人类可读的文件大小(1K, 2M, 3G)
ls -lt                       # 按修改时间排序(最新在前)
ls -ltr                      # 按修改时间倒序(最旧在前)
ls -lS                       # 按文件大小排序(最大在前)
ls -R                        # 递归列出子目录
ls -d */                     # 只列出目录
ls -i                        # 显示 inode 号
ls -1                        # 每行一个文件

# ls -l 输出详解
# -rw-r--r-- 1 alice developers 4096 Jan 15 10:30 report.txt
# │          │ │     │          │    │              │
# 类型+权限  链接数 所有者 所属组   大小  修改时间       文件名

2.2 创建文件与目录

Bash
# touch - 创建空文件 / 更新时间戳
touch file.txt               # 创建空文件(如存在则更新时间戳)
touch file1.txt file2.txt    # 创建多个文件
touch -t 202301150800 f.txt  # 设置指定时间戳

# mkdir - 创建目录(Make Directory)
mkdir mydir                  # 创建目录
mkdir -p a/b/c/d             # 递归创建多级目录(最常用)
mkdir -m 755 mydir           # 创建并设置权限
mkdir dir1 dir2 dir3         # 同时创建多个目录
mkdir -p project/{src,bin,lib,doc,test}  # 创建项目结构(花括号展开)

# 使用 cat / echo 创建带内容的文件
echo "Hello World" > hello.txt          # 创建并写入
cat > config.txt << EOF                 # Here Document 创建文件
server=192.168.1.1
port=8080
EOF

2.3 复制文件与目录

Bash
# cp - 复制(Copy)
cp file1.txt file2.txt        # 复制文件
cp file.txt /tmp/             # 复制到目标目录
cp -r dir1/ dir2/             # 递归复制目录(-r 必须用于目录)
cp -i file.txt /tmp/          # 覆盖前提示(interactive)
cp -v file.txt /tmp/          # 显示复制过程(verbose)
cp -p file.txt /tmp/          # 保留原文件属性(权限、时间戳)
cp -a dir1/ dir2/             # 归档复制(保留所有属性 = -rpd)
cp -u *.txt /backup/          # 只复制更新的文件(update)

# 复制多个文件
cp file1 file2 file3 /dest/   # 复制多个文件到目录
cp *.log /backup/logs/        # 使用通配符复制

2.4 移动与重命名

Bash
# mv - 移动/重命名(Move)
mv old.txt new.txt            # 重命名文件
mv file.txt /tmp/             # 移动文件
mv dir1/ /opt/                # 移动目录(不需要 -r)
mv -i file.txt /tmp/          # 覆盖前提示
mv -v *.log /archive/         # 显示移动过程
mv -n file.txt /tmp/          # 不覆盖已存在文件(no-clobber)
mv -b file.txt /tmp/          # 覆盖前备份(创建 file.txt~ 备份文件)

# 批量重命名(使用 rename)
# Ubuntu: apt install rename
rename 's/\.txt$/\.md/' *.txt        # .txt 改为 .md
rename 's/^/prefix_/' *.jpg          # 添加前缀
rename 'y/A-Z/a-z/' *.TXT            # 大写改小写

2.5 删除文件与目录

Bash
# rm - 删除(Remove)— 注意:Linux 没有回收站!
rm file.txt                   # 删除文件
rm -i file.txt                # 删除前确认
rm -f file.txt                # 强制删除(不提示)
rm -r dir/                    # 递归删除目录
rm -rf dir/                   # 强制递归删除(危险!)
rm -v *.log                   # 显示删除过程

# ⚠️ 危险命令警示
# rm -rf /                   # 删除整个系统(NEVER DO THIS!)
# rm -rf /*                  # 同上
# rm -rf $DIR/               # 如果 $DIR 为空,等同于 rm -rf /

# 安全的删除习惯
# 1. 先 ls 确认,再 rm
ls *.log                      # 先看看有哪些文件
rm *.log                      # 确认后再删除

# 2. 使用 trash-cli 替代 rm
# apt install trash-cli
trash-put file.txt            # 放入回收站
trash-list                    # 查看回收站
trash-restore                 # 恢复文件

# rmdir - 删除空目录
rmdir empty_dir/              # 只能删除空目录
rmdir -p a/b/c/               # 递归删除空的父目录

📖 3. 文件查看命令

Bash
# cat - 查看文件内容(适合小文件)
cat file.txt                  # 查看文件
cat -n file.txt               # 显示行号
cat -b file.txt               # 只给非空行编号
cat file1 file2 > merged      # 合并文件

# less - 分页查看(适合大文件,最常用)
less file.txt
# 操作:空格=下一页, b=上一页, /text=搜索, q=退出, G=末尾, g=开头

# more - 分页查看(只能向前翻页)
more file.txt

# head - 查看文件开头
head file.txt                 # 默认前10行
head -n 20 file.txt           # 前20行
head -c 100 file.txt          # 前100字节

# tail - 查看文件末尾
tail file.txt                 # 默认后10行
tail -n 20 file.txt           # 后20行
tail -f /var/log/syslog       # 实时跟踪文件更新(运维神器)
tail -F /var/log/syslog       # 同上,文件被重建也能跟踪

# wc - 统计字数
wc file.txt                   # 行数 单词数 字节数
wc -l file.txt                # 只统计行数
wc -w file.txt                # 只统计单词数
wc -c file.txt                # 只统计字节数

# nl - 带行号显示
nl file.txt
nl -b a file.txt              # 所有行编号(包括空行)

# tac - 反向显示(cat 倒过来)
tac file.txt                  # 最后一行先显示

# rev - 每行字符翻转
echo "hello" | rev            # olleh

📖 4. 文件查找

4.1 find - 实时搜索(最强大)

Bash
# 基本语法:find [搜索路径] [选项] [动作]

# 按名称查找
find / -name "*.log"                    # 在全盘查找 .log 文件
find /home -name "*.txt"                # 在 /home 下查找
find . -name "config*"                  # 当前目录下查找以config开头的
find . -iname "readme*"                 # 忽略大小写查找

# 按类型查找
find /etc -type f                       # 普通文件
find /etc -type d                       # 目录
find /dev -type l                       # 符号链接
find /dev -type b                       # 块设备

# 按大小查找
find / -size +100M                      # 大于 100MB
find / -size -1k                        # 小于 1KB
find / -size 10M                        # 等于 10MB

# 按时间查找
find /var/log -mtime -7                 # 7天内修改的
find /tmp -mtime +30                    # 30天前修改的
find . -mmin -60                        # 60分钟内修改的
find . -newer reference.txt             # 比某个文件更新的

# 按权限查找
find / -perm 777                        # 权限为 777 的
find / -perm -u+s                       # 设置了 SUID 的
find / -perm /o+w                       # 其他人可写的

# 按所有者查找
find /home -user alice                  # 属于 alice 的
find / -group developers                # 属于 developers 组的
find / -nouser                          # 没有所有者的文件

# 组合条件
find / -name "*.log" -size +10M         # 与(默认AND)
find / -name "*.jpg" -o -name "*.png"   # 或(OR)
find / ! -name "*.txt"                  # 非(NOT)

# 执行动作
find /tmp -name "*.tmp" -delete         # 删除找到的文件
find . -name "*.sh" -exec chmod +x {} \;    # 对每个文件执行命令
find . -name "*.log" -exec ls -lh {} \;     # 查看详情
find . -type f -exec grep -l "error" {} \;  # 查找包含 error 的文件

# xargs 配合(更高效)
find . -name "*.txt" | xargs grep "pattern"       # 在找到的文件中搜索
find . -name "*.log" | xargs -I {} mv {} /backup/  # 移动找到的文件
find . -name "*.tmp" -print0 | xargs -0 rm         # 处理包含空格的文件名

# 实用组合示例
# 查找大于 50MB 的日志文件并按大小排序
find /var/log -name "*.log" -size +50M -exec ls -lh {} \; | sort -k5 -h

# 查找 7天内修改的配置文件
find /etc -type f -name "*.conf" -mtime -7

# 查找并清理空目录
find /path -type d -empty -delete

4.2 locate - 数据库搜索(快速)

Bash
# locate 使用预先建立的数据库搜索,速度极快
# 安装
sudo apt install mlocate      # Ubuntu
sudo yum install mlocate       # CentOS

# 更新数据库(新文件需要先更新才能搜到)
sudo updatedb

# 搜索
locate nginx.conf              # 搜索包含此字符串的路径
locate -i readme               # 忽略大小写
locate -c "*.log"              # 只显示匹配数量
locate -n 10 "*.conf"          # 只显示前10个结果

# locate vs find
# locate:快(查数据库),但可能不是最新的
# find:慢(实时搜索),但结果一定是最新的

4.3 which / whereis / type

Bash
# which - 在 PATH 中查找可执行文件
which python3                  # /usr/bin/python3
which -a python                # 显示所有匹配的

# whereis - 查找命令的二进制、源码和手册
whereis ls                     # ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
whereis -b nginx               # 只查二进制文件
whereis -m nginx               # 只查手册页

# type - 显示命令类型
type cd                        # cd is a shell builtin
type ls                        # ls is aliased to 'ls --color=auto'
type /usr/bin/ls               # /usr/bin/ls is /usr/bin/ls

📖 5. 文件权限

5.1 权限基础

Bash
# Linux 权限模型
# 每个文件有三组权限:所有者(Owner)、所属组(Group)、其他人(Others)
# 每组有三种权限:读(Read)、写(Write)、执行(eXecute)

# ls -l 输出的权限字段:
# -rwxr-xr-- 1 alice developers file.txt
#  |||  |||  |||
#  |||  |||  ||+-- 其他人: 读(r)
#  |||  |||  |+--- 其他人: 无写(-)
#  |||  |||  +---- 其他人: 无执行(-)
#  |||  ||+------- 组: 读(r)
#  |||  |+-------- 组: 无写(-)
#  |||  +--------- 组: 执行(x)
#  ||+------------ 所有者: 读(r)
#  |+------------- 所有者: 写(w)
#  +-------------- 所有者: 执行(x)

# 权限数字表示
# r = 4, w = 2, x = 1
# rwx = 4+2+1 = 7
# r-x = 4+0+1 = 5
# r-- = 4+0+0 = 4

# 常见权限组合
# 755 = rwxr-xr-x  目录、可执行文件
# 644 = rw-r--r--  普通文件
# 700 = rwx------  私有目录
# 600 = rw-------  私密文件(如SSH密钥)
# 777 = rwxrwxrwx  全部权限(不推荐用于生产环境)

5.2 chmod - 修改权限

Bash
# chmod - 修改文件权限

# 数字方式(最常用)
chmod 755 script.sh            # rwxr-xr-x
chmod 644 config.txt           # rw-r--r--
chmod 600 id_rsa               # rw-------
chmod 700 private_dir/         # rwx------

# 符号方式
chmod u+x script.sh            # 给所有者添加执行权限
chmod g+w file.txt             # 给组添加写权限
chmod o-r file.txt             # 移除其他人的读权限
chmod a+r file.txt             # 给所有人添加读权限(a=all)
chmod u=rwx,g=rx,o=r file.txt  # 精确设置

# 递归修改
chmod -R 755 project_dir/      # 递归修改目录和文件
chmod -R u+rwX project_dir/    # X: 只给目录和已有执行权限的文件添加执行权限

# 引用其他文件的权限
chmod --reference=file1.txt file2.txt  # 让 file2 的权限和 file1 相同

5.3 chown / chgrp - 修改所有者和组

Bash
# chown - 修改所有者(需要 root 权限)
chown alice file.txt            # 修改所有者
chown alice:developers file.txt # 同时修改所有者和组
chown :developers file.txt      # 只修改组
chown -R alice:alice /home/alice/  # 递归修改

# chgrp - 修改所属组
chgrp developers file.txt       # 修改组
chgrp -R developers project/    # 递归修改

5.4 特殊权限

SUID(Set User ID)

Bash
# SUID: 执行文件时,以文件所有者的身份运行(不是执行者的身份)
# 常见例子:passwd 命令需要修改 /etc/shadow,但普通用户没有权限
# passwd 设置了 SUID,执行时以 root 身份运行

ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 Jul 15 00:00 /usr/bin/passwd
#    ^
#    s 表示 SUID 被设置

# 设置 SUID
chmod u+s executable           # 符号方式
chmod 4755 executable          # 数字方式(4 = SUID)

# 查找系统中所有 SUID 文件(安全审计时常用)
find / -perm -u+s -type f 2>/dev/null

SGID(Set Group ID)

Bash
# SGID 用于文件:执行时以文件所属组的身份运行
# SGID 用于目录:在该目录下创建的文件自动继承目录的组

# 团队协作场景
mkdir /shared/project
chgrp developers /shared/project
chmod g+s /shared/project       # 设置 SGID
chmod 2775 /shared/project     # 数字方式(2 = SGID)

# 验证:alice 在 /shared/project 创建的文件
# 自动属于 developers 组,而不是 alice 的默认组
touch /shared/project/newfile.txt
ls -l /shared/project/newfile.txt
# -rw-r--r-- 1 alice developers ...

# 查找 SGID 文件
find / -perm -g+s -type f 2>/dev/null

Sticky Bit(粘滞位)

Bash
# Sticky Bit:用于目录,只有文件所有者和 root 可以删除其中的文件
# 典型例子:/tmp 目录

ls -ld /tmp
# drwxrwxrwt 10 root root 4096 Jan 15 10:00 /tmp
#          ^
#          t 表示 Sticky Bit 被设置

# 设置 Sticky Bit
chmod +t shared_dir/            # 符号方式
chmod 1777 shared_dir/          # 数字方式(1 = Sticky)

# 效果:所有用户可以在 /tmp 创建文件
# 但 alice 不能删除 bob 创建的文件

特殊权限数字总结

Bash
# 四位数字权限:
# 第一位: 特殊权限
#   4 = SUID
#   2 = SGID
#   1 = Sticky Bit
# 后三位: 标准权限(owner/group/others)

chmod 4755 file    # SUID + rwxr-xr-x
chmod 2775 dir     # SGID + rwxrwxr-x
chmod 1777 dir     # Sticky + rwxrwxrwx
chmod 6755 file    # SUID + SGID + rwxr-xr-x

5.5 ACL(Access Control List)

Bash
# ACL 提供更精细的权限控制,可以为特定用户/组设置权限

# 查看 ACL
getfacl file.txt
# # file: file.txt
# # owner: alice
# # group: developers
# user::rwx
# group::r-x
# other::r--

# 设置 ACL
setfacl -m u:bob:rwx file.txt          # 给 bob 用户 rwx 权限
setfacl -m g:testers:rx file.txt       # 给 testers 组 rx 权限
setfacl -m u:charlie:--- file.txt      # 禁止 charlie 任何访问

# 递归设置
setfacl -R -m u:bob:rx project_dir/    # 递归给 bob 读和执行权限

# 默认 ACL(对新创建的文件自动生效)
setfacl -d -m u:bob:rwx shared_dir/    # 目录下新文件自动给 bob rwx

# 删除 ACL
setfacl -x u:bob file.txt             # 删除 bob 的 ACL
setfacl -b file.txt                    # 删除所有 ACL

# 备份和恢复 ACL
getfacl -R /project > acl_backup.txt   # 备份
setfacl --restore=acl_backup.txt       # 恢复

📖 6. 硬链接与软链接

6.1 概念对比

Text Only
文件系统结构:
                    inode 100
                   ┌─────────┐
文件名  ──────────►│ 元数据    │
                   │ 权限/大小 │
                   │ 时间戳    │──────► 数据块
                   │ 链接计数  │
                   └─────────┘

硬链接:多个文件名指向同一个 inode
┌──────────┐
│ file1.txt │─────┐
└──────────┘     │    inode 100
                  ├──►┌─────────┐
┌──────────┐     │    │ 链接数=2 │──► 数据
│ file2.txt │─────┘    └─────────┘
└──────────┘

软链接:一个文件指向另一个文件名
┌──────────┐      inode 200       inode 100
│ link.txt  │────►┌─────────┐    ┌─────────┐
└──────────┘      │"file.txt"│──►│ 实际数据  │
                  └─────────┘    └─────────┘
Bash
# 创建硬链接
ln original.txt hardlink.txt

# 验证:两个文件有相同的 inode
ls -li original.txt hardlink.txt
# 100 -rw-r--r-- 2 alice alice 100 Jan 15 file.txt
# 100 -rw-r--r-- 2 alice alice 100 Jan 15 hardlink.txt
# ^inode相同        ^链接数为2

# 硬链接的特点
# ✅ 修改任何一方,另一方同步更新(指向相同数据)
# ✅ 删除原文件,硬链接依然可用(数据未删除)
# ✅ 不能跨文件系统(必须在同一分区)
# ❌ 不能对目录创建硬链接(防止循环引用)
# ❌ 不能跨分区

echo "Hello World" > original.txt
ln original.txt link.txt
echo "Modified" >> original.txt
cat link.txt                    # 能看到 "Modified"
rm original.txt
cat link.txt                    # 仍然可用!
Bash
# 创建软链接(类似 Windows 的快捷方式)
ln -s /path/to/original.txt symlink.txt
ln -s /usr/local/bin/python3.10 /usr/local/bin/python3

# 验证
ls -l symlink.txt
# lrwxrwxrwx 1 alice alice 18 Jan 15 symlink.txt -> /path/to/original.txt
# ^
# l 表示这是一个符号链接

# 软链接的特点
# ✅ 可以跨文件系统/分区
# ✅ 可以对目录创建软链接
# ✅ 可以看到指向的目标(ls -l)
# ❌ 删除原文件后,软链接失效(悬空链接)
# ❌ 软链接有自己的 inode(不同于原文件)

# 常见应用
# 1. 版本切换
ln -sf /usr/local/java/jdk-17 /usr/local/java/current

# 2. 简化路径
ln -s /very/long/path/to/config /etc/myapp.conf

# 3. 共享库
ls -l /lib/x86_64-linux-gnu/libc.so*
# libc.so.6 -> libc-2.31.so

6.4 硬链接 vs 软链接总结

特性 硬链接 软链接
inode 与原文件相同 有自己的 inode
跨文件系统 ❌ 不可以 ✅ 可以
链接目录 ❌ 不可以 ✅ 可以
原文件删除 不影响,数据依然在 失效(悬空链接)
文件大小 与原文件相同 存储目标路径的大小
相对路径 N/A 相对于链接所在目录
识别方式 ls -i 看 inode ls -l 看 -> 指向

📖 7. 通配符(Globbing)

Bash
# Shell 通配符用于文件名匹配模式

# * 匹配任意数量的任意字符
ls *.txt                       # 所有 .txt 文件
ls file*                       # 以 file 开头的所有文件
ls *report*                    # 包含 report 的所有文件

# ? 匹配单个任意字符
ls file?.txt                   # file1.txt, fileA.txt 等
ls ???.log                     # 三个字符的 .log 文件

# [] 匹配方括号内的任一字符
ls file[123].txt               # file1.txt, file2.txt, file3.txt
ls file[a-z].txt               # filea.txt, fileb.txt, ...
ls file[!0-9].txt              # 非数字的(file 后面一个非数字字符)
ls [A-Z]*.txt                  # 大写字母开头的 .txt 文件

# {} 花括号展开(Brace Expansion,不是通配符但很实用)
echo {a,b,c}                   # a b c
mkdir dir_{01..10}             # 创建 dir_01 到 dir_10
cp file.{txt,bak}              # 等同于 cp file.txt file.bak
touch {jan,feb,mar}_{2024,2025}.log  # 创建6个文件

# 实用示例
# 复制所有非 .log 文件
cp !(*.log) /backup/           # 需要 shopt -s extglob

# 扩展通配符(需开启 extglob)
shopt -s extglob
ls !(*.log)                    # 排除 .log 文件
ls @(*.txt|*.md)               # .txt 或 .md 文件
ls ?(ab)c                      # c 或 abc
ls +(ab)                       # ab, abab, ababab...
ls *(ab)                       # 空, ab, abab, ababab...

📖 8. 文件属性

Bash
# stat - 查看文件详细信息
stat file.txt
#   File: file.txt
#   Size: 4096       Blocks: 8          IO Block: 4096   regular file
# Device: fd01h/64769d    Inode: 131073    Links: 1
# Access: (0644/-rw-r--r--)  Uid: ( 1000/  alice)   Gid: ( 1000/  alice)
# Access: 2024-01-15 10:30:00.000000000 +0800
# Modify: 2024-01-15 10:30:00.000000000 +0800
# Change: 2024-01-15 10:30:00.000000000 +0800

# 三种时间
# atime (Access time): 最后访问时间
# mtime (Modify time): 最后内容修改时间
# ctime (Change time): 最后元数据修改时间(权限、所有者等)

# lsattr / chattr - 文件特殊属性
lsattr file.txt                # 查看特殊属性

# 设置不可修改属性(即使 root 也不能删除/修改)
sudo chattr +i important.conf  # 设置 immutable
sudo chattr -i important.conf  # 取消 immutable

# 设置只能追加属性(适合日志文件)
sudo chattr +a logfile.log     # 只能追加,不能删除/修改已有内容

📖 9. 实战示例

示例1:项目目录结构创建

Bash
#!/bin/bash
# 创建标准 Web 项目目录结构

PROJECT="mywebapp"

mkdir -p "$PROJECT"/{src/{main/{java,resources},test},docs,scripts,config}
mkdir -p "$PROJECT"/src/main/java/com/example/{controller,service,model,config}
mkdir -p "$PROJECT"/src/main/resources/{static/{css,js,images},templates}

# 创建基本文件
touch "$PROJECT"/README.md
touch "$PROJECT"/.gitignore
touch "$PROJECT"/config/{dev,test,prod}.properties

# 设置权限
chmod -R 755 "$PROJECT"/scripts/
chmod 644 "$PROJECT"/config/*.properties

# 显示结构
tree "$PROJECT"

示例2:批量文件整理

Bash
#!/bin/bash
# 按文件扩展名分类整理文件

SRC_DIR="$HOME/Downloads"
DEST_DIR="$HOME/Organized"

# 创建分类目录
mkdir -p "$DEST_DIR"/{Images,Documents,Videos,Music,Archives,Others}

# 分类移动
cd "$SRC_DIR"
for file in *; do
    [ -f "$file" ] || continue  # &&前一个成功才执行后一个;||前一个失败才执行
    case "${file##*.}" in
        jpg|jpeg|png|gif|bmp|svg)   mv "$file" "$DEST_DIR/Images/" ;;
        pdf|doc|docx|txt|md|xlsx)   mv "$file" "$DEST_DIR/Documents/" ;;
        mp4|avi|mkv|mov|wmv)        mv "$file" "$DEST_DIR/Videos/" ;;
        mp3|wav|flac|aac)           mv "$file" "$DEST_DIR/Music/" ;;
        zip|tar|gz|bz2|xz|rar)     mv "$file" "$DEST_DIR/Archives/" ;;
        *)                          mv "$file" "$DEST_DIR/Others/" ;;
    esac
done

echo "文件整理完成!"

示例3:权限审计脚本

Bash
#!/bin/bash
# 检查系统中可能不安全的文件权限

echo "=== 安全权限审计报告 ==="
echo "生成时间: $(date)"
echo ""

# 1. 查找全局可写文件
echo "--- 全局可写文件(非 /tmp 和 /proc)---"
find / -path /tmp -prune -o -path /proc -prune -o \
    -type f -perm -o+w -print 2>/dev/null

# 2. 查找无主文件
echo ""
echo "--- 无主文件 ---"
find / -path /proc -prune -o -nouser -print 2>/dev/null

# 3. 查找 SUID/SGID 文件
echo ""
echo "--- SUID 文件 ---"
find / -perm -u+s -type f 2>/dev/null

echo ""
echo "--- SGID 文件 ---"
find / -perm -g+s -type f 2>/dev/null

# 4. 检查关键文件权限
echo ""
echo "--- 关键文件权限检查 ---"
for file in /etc/passwd /etc/shadow /etc/sudoers; do  # Shell for循环
    if [ -f "$file" ]; then  # 条件测试:-f文件存在 -d目录存在 -z空字符串
        echo "$file: $(stat -c '%a %U:%G' "$file")"  # $()命令替换:执行命令并获取输出
    fi
done

📖 10. 面试要点

高频面试题

Q1:硬链接和软链接的区别?什么场景使用哪种?

硬链接与原文件共享 inode,删除原文件不受影响,但不能跨文件系统、不能链接目录。软链接有独立 inode、存储指向路径,可以跨文件系统、可以链接目录,但原文件删除会导致悬空链接。版本切换用软链接(如 java/current -> jdk-17),数据备份/防误删用硬链接。

Q2:解释 chmod 755 的含义

755 = rwxr-xr-x。所有者有读、写、执行权限(7=4+2+1),组用户和其他用户有读和执行权限(5=4+0+1)。常用于目录和可执行脚本。

Q3:什么是 SUID?有什么安全风险?

SUID(Set User ID) 使程序在执行时以文件所有者身份运行。如 passwd 命令以 root 身份运行来修改 /etc/shadow。安全风险:如果 SUID 程序有漏洞,攻击者可能获得 root 权限。应定期审计 SUID 文件:find / -perm -u+s -type f

Q4:find 和 locate 的区别?

find 实时遍历文件系统,结果准确但较慢;locate 查询预建数据库,极快但可能不是最新的,需要 updatedb 更新数据库。生产环境排障用 find,日常快速查找用 locate

Q5:如何找出系统中大于 100MB 的文件?

Bash
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h  # |管道:将前一命令的输出作为后一命令的输入
# 或
du -ah / 2>/dev/null | sort -rh | head -20

🔧 练习题

基础练习

  1. 创建目录结构 ~/practice/{dir1,dir2,dir3}/{sub1,sub2} 并验证
  2. 创建一个文件,分别给所有者 rwx、组 rx、其他 r 权限
  3. 创建一个硬链接和一个软链接,删除原文件后分别查看效果

进阶练习

  1. 使用 find 查找 /var/log 下 7 天内修改过的大于 1MB 的文件
  2. 为共享目录设置 SGID,验证新文件的组继承
  3. 使用 ACL 让特定用户对文件有只读权限

综合练习

  1. 编写脚本:自动创建项目目录结构并设置合适的权限
  2. 编写脚本:查找并报告系统中的 SUID 文件
  3. 编写脚本:按文件类型自动整理 Downloads 目录

✅ 自我检查

  • 能熟练使用 ls/cd/cp/mv/rm/mkdir 等命令
  • 能用 find 进行各种条件的文件搜索
  • 理解 rwx 权限模型和数字表示
  • 知道 SUID/SGID/Sticky Bit 的作用和使用场景
  • 能区分硬链接和软链接
  • 能使用 ACL 设置精细权限
  • 能编写文件管理相关的 Shell 脚本

上一章01-Linux基础入门 下一章03-文本处理三剑客