04 - 文件与目录管理

文件与目录管理是 Linux 命令行最核心的基本功。从查看文件到复制移动,从搜索查找到分析类型,这些操作将占据你日常使用的绝大部分时间。本章系统性地覆盖所有基础命令及其组合用法。


4.1 路径的概念

在深入命令之前,必须先理解 Linux 路径系统。

4.1.1 绝对路径 vs 相对路径

类型含义示例
绝对路径/(根目录)开始的完整路径/home/alice/Documents/report.txt
相对路径从当前工作目录开始的路径Documents/report.txt
pwd # 查看当前工作目录(Print Working Directory)
# 输出: /home/alice
 
# 以下两条命令等价(假设当前在 /home/alice)
cat /home/alice/Documents/report.txt # 绝对路径
cat Documents/report.txt # 相对路径

4.1.2 特殊目录符号

符号含义
.当前目录
..上级目录(父目录)
~当前用户的主目录(等价于 $HOME
~username指定用户的主目录
-上一次所在的工作目录(cd - 专用)
cd .. # 返回上级目录
cd ../.. # 返回上两级
cd ~ # 回到主目录
cd - # 回到上一次所在目录
ls . # 列出当前目录(与 ls 等价)
cp ../file.txt . # 将上级目录的文件复制到当前目录

4.2 基础浏览命令

4.2.1 ls — 列出目录内容

ls # 列出当前目录(简洁模式)
ls -l # 详细列表(权限、大小、时间)
ls -a # 显示隐藏文件(以 . 开头)
ls -la # 详细列表 + 隐藏文件(最常用组合)
ls -lh # 详细列表 + 人类可读的文件大小(K/M/G)
ls -lt # 按修改时间排序(最新的在前)
ls -ltr # 按修改时间反向排序(最旧的在最前)
ls -R # 递归列出子目录
ls -S # 按文件大小排序
ls -i # 显示 inode 号
ls -d */ # 只列出目录(不列出文件)
# 理解 ls -l 输出的每一列
$ ls -l
# -rw-r--r-- 1 alice users 4096 Mar 15 10:30 report.txt
# └─┬──────┘ │ └─┬─┘ └─┬─┘ └─┬─┘ └──────┬─────┘ └──┬─────┘
# 权限 链接数 所有者 所属组 大小 修改时间 文件名

4.2.1b 文件类型标识符

ls -l 输出的第一个字符表示文件类型,这是 Linux “一切皆文件” 的体现:

符号类型说明常见位置
-普通文件文本、二进制、图片等到处都是
d目录文件夹/home, /tmp
l符号链接指向另一个文件的快捷方式/usr/bin/python3 -> python3.11
c字符设备按字符读写的设备/dev/tty, /dev/null
b块设备按块读写的设备(硬盘等)/dev/sda, /dev/nvme0n1
p命名管道进程间通信 (FIFO)/run/initctl
s套接字网络/进程间通信端点/run/docker.sock, /var/run/mysqld/mysqld.sock
# 实际观察各种文件类型
ls -l /dev/sda       # brw-rw----  块设备
ls -l /dev/null      # crw-rw-rw-  字符设备
ls -l /usr/bin/python3 # lrwxrwxrwx  符号链接
ls -l /tmp           # drwxrwxrwt  目录
ls -l /run/docker.sock # srw-rw----  套接字
 
# 快速统计目录下各类文件数量
ls -l | awk '{print $1}' | sort | uniq -c | sort -rn
# 输出示例:
#  15 -rw-r--r--   (普通文件)
#   8 drwxr-xr-x   (目录)
#   2 lrwxrwxrwx   (符号链接)

目录权限的特殊含义

  • r (读):可以 ls 列出目录内容
  • w (写):可以在目录下创建/删除文件(需要 x 权限配合)
  • x (执行):可以 cd 进入目录,或访问目录下的文件元数据
# 目录权限示例
drwxr-xr-x  # 755 — 能进目录、能看内容、不能改
drwx------  # 700 — 只有所有者能进(私有目录)
drwxrwxrwx  # 777 — 所有人可读写执行(危险!)
drwxrwxrwt  # 1777 + Sticky — 所有人可写,但只能删自己的(/tmp)

4.2.2 cd — 切换目录

cd /etc # 切换到 /etc
cd # 无参数 = 回到主目录
cd ~/Downloads # 切换到主目录下的 Downloads
cd "$HOME/.config" # 使用环境变量

4.2.3 pwd — 显示当前工作目录

pwd # 显示逻辑路径,如 /home/alice
pwd -P # 显示物理路径(解析符号链接后的真实路径)

4.3 目录管理

4.3.1 mkdir — 创建目录

mkdir project # 创建单个目录
mkdir -p a/b/c/d # 递归创建父目录(-p = parents)
mkdir -m 755 shared # 创建并指定权限(不用默认 umask)
mkdir dir1 dir2 dir3 # 同时创建多个目录
mkdir -p project/{src,docs,tests,bin} # 花括号展开,批量创建

4.3.2 rmdir — 删除空目录

rmdir empty_dir # 只能删除空目录
rmdir -p a/b/c # 递归删除空的子目录链
 
# 实际上很多人直接用 rm -r 代替

4.4 文件操作

4.4.1 touch — 创建空文件 / 更新时间戳

touch newfile.txt # 创建空文件(如果不存在)
touch existing.txt # 更新文件的修改时间到"现在"
touch -t 202512312359 file.txt # 设置指定的时间戳
touch -a file.txt # 只更新访问时间(access time)
touch -m file.txt # 只更新修改时间(modification time)

4.4.2 cp — 复制

cp source.txt dest.txt # 复制文件
cp -i source.txt dest.txt # 覆盖前询问(-i = interactive)
cp -r dir1/ dir2/ # 递归复制目录(-r = recursive)
cp -a dir1/ dir2/ # 归档模式复制(保留权限、时间、符号链接等)
cp -v source.txt dest.txt # 显示复制过程(-v = verbose)
cp -u source.txt dest.txt # 仅当源文件更新时才覆盖(-u = update)
cp -p source.txt dest.txt # 保留权限和时间戳
cp file1 file2 file3 dest_dir/ # 复制多个文件到同一目录

4.4.3 mv — 移动 / 重命名

mv oldname.txt newname.txt # 重命名文件
mv file.txt /path/to/dest/ # 移动文件
mv -i source.txt dest.txt # 覆盖前询问
mv -n source.txt dest.txt # 不覆盖已有文件
mv *.log archive/ # 移动所有 .log 文件

4.4.4 rm — 删除

rm file.txt # 删除文件
rm -i file.txt # 删除前确认
rm -f file.txt # 强制删除(不提示,不报错如果不存在)
rm -r dir/ # 递归删除目录及所有内容
rm -rf dir/ # 强制递归删除——危险命令
rm -- -file.txt # 删除以 - 开头的文件 实际上现在linux操作系统支持**选取

rm -rf / 是著名的”自杀命令”——会尝试删除系统所有文件。现代系统通常有保护(--preserve-root),但仍需极度谨慎。

4.4.5 安全删除建议

# 使用 trash-cli 代替 rm,文件可回收
# 使用你的包管理器安装:trash-cli
trash-put file.txt # 删除(移入回收站)
trash-list # 查看回收站
trash-restore # 交互式恢复
trash-empty # 清空回收站

4.5 文件信息查看

4.5.1 file — 判断文件类型

Linux 不靠扩展名判断文件类型,file 命令通过读取文件头部魔数(magic number)来识别:

file document.pdf
# 输出: document.pdf: PDF document, version 1.4
 
file script.sh
# 输出: script.sh: Bourne-Again shell script, ASCII text executable
 
file /bin/ls
# 输出: /bin/ls: ELF 64-bit LSB pie executable, x86-64, ...
 
file image.png
# 输出: image.png: PNG image data, 1920 x 1080, 8-bit/color RGBA
 
file archive.tar.gz
# 输出: archive.tar.gz: gzip compressed data, from Unix
 
file -i document.pdf # 显示 MIME 类型
# 输出: document.pdf: application/pdf; charset=binary

4.5.2 stat — 查看文件详细信息

stat file.txt
# 输出:
# File: file.txt
# Size: 4096 Blocks: 8 IO Block: 4096 regular file
# Device: 259,2 Inode: 1234567 Links: 1
# Access: (0644/-rw-r--r--) Uid: (1000/ alice) Gid: (1000/ users)
# Access: 2024-03-15 10:30:00.000000000 +0800
# Modify: 2024-03-14 15:20:00.000000000 +0800
# Change: 2024-03-14 15:20:00.000000000 +0800
# Birth: 2024-01-01 00:00:00.000000000 +0800

三个时间戳的含义:

时间含义触发条件
Access (atime)最后访问时间读取文件内容或执行
Modify (mtime)最后修改时间文件内容被修改
Change (ctime)最后状态变更时间权限、所有者、链接数等元数据变更

4.5.3 type — 查看命令类型

type ls
# 输出: ls is aliased to `ls --color=auto' (如果是别名)
# 或: ls is /usr/bin/ls (如果是外部命令)
 
type cd
# 输出: cd is a shell builtin (内建命令)
 
type -a echo # 列出所有可能(别名、内建、外部)
type -t ls # 只显示类型(alias/keyword/builtin/file)

4.5.4 which / whereis — 查找命令位置

which python # 在 PATH 中查找可执行文件
which -a python # 显示所有匹配(所有路径)
whereis python # 查找二进制、源码和 man 手册页位置

4.6 文件搜索

4.6.1 find — 强大的文件搜索

find 是 Linux 最强大也最复杂的文件搜索工具。基本语法:

find [搜索路径] [匹配条件] [动作]

按文件名搜索:

find /home -name "*.txt" # 精确匹配(区分大小写)
find /home -iname "*.TXT" # 忽略大小写
find /home -name "*.txt" -o -name "*.md" # 或逻辑(-o = OR)

按类型搜索:

find / -type f -name "*.conf" # 只找普通文件
find / -type d -name "config" # 只找目录
find / -type l -name "*.so" # 只找符号链接

按大小搜索:

find /var/log -size +100M # 大于 100MB 的文件
find /var/log -size -10k # 小于 10KB 的文件
find / -size +1G -size -5G # 1GB 到 5GB 之间
find /tmp -empty # 空文件或空目录

按时间搜索:

find /home -mtime -1 # 最近 1 天内修改的文件
find /home -mtime +7 # 7 天前修改的文件
find /home -mmin -30 # 最近 30 分钟内修改的文件
find /home -atime -1 # 最近 1 天内访问过的文件
find /home -newer reference.txt # 比 reference.txt 更新的文件

按权限搜索:

find / -perm 777 # 权限恰好为 777 的文件
find / -perm -u+s # 设置了 SUID 位的文件
find /home -user alice # 属于 alice 用户的文件
find /home -group users # 属于 users 组的文件

对搜索结果执行操作:

find . -name "*.bak" -delete # 删除所有 .bak 文件 现代linux中可以先find列出再由第二次指令rm删除(上一条指令)
find . -name "*.log" -exec rm {} \; # 对每个找到的文件执行 rm
find . -name "*.txt" -exec mv {} {}.old \; # 批量重命名
find . -type d -exec chmod 755 {} \; # 修改所有目录权限
 
# -exec ... + 更高效(批量传递,减少进程开销)
find . -name "*.txt" -exec wc -l {} + # 统计所有 .txt 文件的行数
 
# 交互式确认
find . -name "*.tmp" -ok rm {} \; # 每次操作前询问(y/n)

4.6.2 locate — 快速文件名搜索

locate 通过预先建立的数据库搜索,速度比 find 快很多,但结果可能不是实时的:

# 安装 mlocate(通常系统已有)
# Debian/Ubuntu: sudo apt install mlocate
# Fedora: sudo dnf install mlocate
# Arch: sudo pacman -S mlocate
 
sudo updatedb # 更新数据库(通常由 cron 自动运行)
locate fstab # 搜索包含 "fstab" 的文件路径
locate -i fstab # 忽略大小写
locate -c nginx # 统计匹配数量
locate -l 10 nginx # 限制显示前 10 条
locate -e nginx # 只显示实际存在的文件
locate -r '\.conf$' # 使用正则表达式(搜索 .conf 结尾)

4.7 通配符与 Glob 模式

Shell 的通配符(glob)扩展对于高效文件操作至关重要。

模式含义示例
*匹配任意字符(0 个或多个)*.txt 匹配所有 .txt 文件
?匹配任意单个字符file?.txt 匹配 file1.txt, fileA.txt
[abc]匹配集合中任一字符file[123].txt 匹配 file1.txt, file2.txt, file3.txt
[a-z]匹配字符范围内任一file[a-c].txt 匹配 fileA.txt, fileB.txt, fileC.txt
[!abc]匹配不在集合中的字符file[!0-9].txt 排除数字
{a,b,c}花括号展开(不是严格 glob){src,test}/main.gosrc/main.go test/main.go
**递归匹配(需 globstar 选项)**/*.go 递归匹配所有目录的 .go 文件
# 实用示例
ls *.log # 列出所有 .log 文件
cp /data/{2023,2024}/*.csv ./ # 复制两个年份的 CSV
rm tmp.[0-9]* # 删除 tmp.0, tmp.1, tmp.123...
ls file.??? # 匹配 file.txt, file.log, file.jpg...
 
# 启用递归 glob(bash 4.0+)
shopt -s globstar # 启用 **
echo **/*.md # 递归列出所有 .md 文件
shopt -u globstar # 恢复禁用

4.8 路径与命令的技巧

4.8.1 dirnamebasename

dirname /home/alice/file.txt
# 输出: /home/alice
 
basename /home/alice/file.txt
# 输出: file.txt
 
basename /home/alice/file.txt .txt
# 输出: file (去掉后缀)
 
# 在脚本中的经典用法
FILEPATH="/var/log/nginx/access.log"
DIR=$(dirname "$FILEPATH")
FILE=$(basename "$FILEPATH")
realpath ./relative/path # 解析为绝对路径
realpath -m /nonexistent/path # 即使路径不存在也标准化
readlink -f /usr/bin/python # 递归跟随符号链接,返回最终目标

4.9 实战技巧

4.9.1 批量重命名

# 将所有 .txt 改为 .md
for f in *.txt; do mv "$f" "${f%.txt}.md"; done
 
# 使用 rename 工具(更强大)
# 安装: 使用你的包管理器安装 perl-rename 或 rename
rename 's/\.txt$/\.md/' *.txt # Perl 风格 rename
rename 's/ /_/g' * # 将所有空格替换为下划线

4.9.2 查找并删除重复文件

# 查找重复文件(按内容哈希)
find . -type f -exec md5sum {} + | sort | uniq -w32 -dD
 
# 查找并列出大文件(Top 10)
find / -type f -exec du -h {} + 2>/dev/null | sort -rh | head -10

4.9.3 快速清空文件内容

> file.log # 最快方式:重定向清空
truncate -s 0 file.log # truncate 命令
echo -n > file.log # echo 方式
true > file.log # true 重定向方式

4.9.4 目录大小快速分析

du -sh * # 当前目录下每个文件/目录的大小
du -sh */ # 只统计目录
du -h --max-depth=1 /var # 只统计第一层
ncdu # 交互式磁盘使用分析器(需安装)

4.10 常见陷阱

陷阱说明正确做法
cp dir1 dir2 未加 -r复制目录必须加 -rcp -r dir1 dir2
文件名包含空格rm My File.txt 会尝试删除 My 和 File.txtrm "My File.txt" 或用 \ 转义
rm -rf / 路径根目录误删永远确认路径,使用 trash-cli
find 中未加引号find . -name *.txt*.txt 会被 shell 先行展开find . -name "*.txt"
忘记 -p 选项mkdir a/b/c 若 a 或 b 不存在则失败mkdir -p a/b/c

4.11 相关链接