文件操作
Linux 运维基础 · 第三章 目标:掌握文件增删改查、查找搜索、归档压缩的全套操作
1. 概述#
运维日常工作就是跟文件打交道:看日志、找配置、备份数据、清理旧文件。本章覆盖从"看一眼"到"打包带走"的完整操作链路。
2. 查看文件与目录#
2.1 ls — 列出目录内容#
ls 是最常用的命令,没有之一。重点记参数组合:
# 基础用法
ls # 列出当前目录
ls /etc/nginx/ # 列出指定目录
# 常用参数
ls -l # 长格式:权限、大小、时间、所有者
ls -a # 显示隐藏文件(以 . 开头)
ls -h # 人类可读的大小(K、M、G)
ls -t # 按修改时间排序
ls -r # 倒序排列
ls -S # 按文件大小排序常用参数组合(运维速查)#
| 命令 | 含义 | 使用场景 |
|---|---|---|
ls -lah | 长格式 + 显示所有 + 人类可读 | 最常用组合,看目录全貌 |
ls -ltr | 长格式 + 按时间 + 倒序 | 看最近修改的文件(最新的在最后) |
ls -lSh | 长格式 + 按大小 + 人类可读 | 找大文件 |
ls -R | 递归列出所有子目录 | 看整个目录树(通常不如 tree 好用) |
ls -ld /etc | 只看目录本身,不看目录内容 | 查看目录自身的权限/时间 |
# 示例:找当前目录下最新的 5 个文件
ls -lt | head -6 # 第 1 行是 total,后面 5 行是文件
# 示例:找当前目录下最大的 5 个文件
ls -lSh | head -62.2 tree — 目录树#
tree # 显示当前目录树
tree /etc/nginx/ # 显示 Nginx 配置的目录结构
tree -L 2 # 只显示 2 层深度
tree -d # 只显示目录,不显示文件
tree -h # 显示文件大小
tree -L 2 -h /opt/ # 看 /opt 下两层目录结构 + 文件大小注意:tree 不是所有发行版预装。RHEL 系(Rocky / AlmaLinux / CentOS Stream)用 dnf install tree,Debian 系(Ubuntu 等)用 apt install tree(老系统上 yum 仍可用,但 RHEL 8+ 已由 dnf 取代)。
3. 增删改移#
3.1 mkdir — 创建目录#
mkdir logs # 创建一个目录
mkdir -p /opt/app/logs # 递归创建(父目录不存在时自动创建)
mkdir -m 750 secure_dir # 创建时直接指定权限mkdir -p 是运维写脚本时的必备参数——不在意目录存不存在,需要就建。
3.2 touch — 创建空文件 / 更新时间戳#
touch newfile.txt # 文件不存在:创建空文件
touch existing.log # 文件存在:更新 mtime 和 atime 为当前时间
touch -t 202501010000 old.log # 手动指定时间戳3.3 cp — 复制#
cp source.txt dest.txt # 复制文件
cp -r dir1/ dir2/ # 递归复制整个目录
cp -p source.txt dest.txt # 保留权限、时间戳等属性(preserve)
cp -v source.txt dest.txt # 显示复制过程(verbose)
cp -i source.txt dest.txt # 覆盖前询问(interactive)
cp -f source.txt dest.txt # 强制覆盖
cp -a dir1/ dir2/ # 归档模式(= -dpR):保留所有属性 + 递归推荐:日常手动复制用 cp -i 防误覆盖,写脚本和备份用 cp -a 保留完整属性。
3.4 mv — 移动 / 重命名#
Linux 没有单独的"重命名"命令,mv 同时负责移动和重命名:
mv oldname.txt newname.txt # 重命名(同目录内移动)
mv file.txt /opt/backup/ # 移动到其他目录
mv -i file.txt /opt/ # 移动前,目标已有同名文件时询问3.5 rm — 删除(危险操作)#
rm file.txt # 删除文件
rm -r dir/ # 递归删除目录
rm -f file.txt # 强制删除(不询问,不报错)
rm -rf dir/ # ⚠️ 亡命组合:强制递归删除,无法撤销!
rm -i file.txt # 逐一确认删除(相对安全)rm -rf 的警示#
Linux 没有回收站,
rm删了就是删了。养成"先ls/find -print看清再删"的肌肉记忆。
# 永远不要执行
rm -rf / # 删除整个系统——现代系统有保护,但仍极度危险
rm -rf * # 删掉当前目录所有内容
rm -rf /home /usr # 多个参数同时删,灾难级
# 危险的变量为空陷阱
rm -rf $DIR/*
# 如果 DIR 变量为空,实际执行的是 rm -rf /* ← 删全系统
# 安全做法
[ -n "$DIR" ] && rm -rf "$DIR"/* # 先检查变量非空
# 更安全的做法:用 find + rm,至少能预览3.6 ln — 软链接 / 硬链接(实操对照)#
概念(inode、link count、能否跨分区/链目录)见第二章 ,这里只给最常用的实操:
# 硬链接:同一个 inode 的第二个名字(不加参数)
ln target.txt hardlink.txt
# 软链接:一个独立的"指针文件",存的是目标路径(-s)
ln -s /opt/app/current/bin/app /usr/local/bin/app
# 对照观察:硬链接与源 inode 相同、link count=2;软链接 inode 不同、类型是 l
ls -li target.txt hardlink.txt /usr/local/bin/app
# 实战:软链接做版本切换(灰度 / 回滚一键完成)
ln -sfn /opt/app/v2 /opt/app/current # -n 防止把链接建到已有目录内部,-f 覆盖旧链接关键坑:ln -s 的目标建议写绝对路径;重建一个已存在的软链接要用 ln -sfn,否则会在旧链接指向的目录里再套一层链接。软链接删源即断,硬链接不能跨文件系统、不能指向目录。
4. 搜索文件:find#
find 是文件搜索的瑞士军刀。语法特殊:路径 + 条件 + 动作。
4.1 按名字搜索#
# 在当前目录下找名字完全匹配的文件
find . -name "nginx.conf"
# 通配符搜索
find /etc -name "*.conf" # 找所有 .conf 文件
# 忽略大小写
find / -iname "README*" # 找各类 README4.2 按时间搜索#
find /app/logs -mtime -7 # 7天内修改过的文件
find /app/logs -mtime +7 # 7天前修改过的文件
find /app/logs -mtime 7 # 恰好7天前修改
find /app/logs -atime +30 # 30天内未被访问过的文件
find . -mmin -60 # 60分钟内修改过的文件
find . -cmin +120 # 2小时前状态变更的文件4.3 按大小搜索#
find / -size +100M # 大于 100MB 的文件
find / -size -10k # 小于 10KB 的文件
find /data -size +1G -size -5G # 1GB 到 5GB 之间的文件
find . -empty # 找空文件/空目录4.4 按权限搜索#
find / -perm 777 # 权限恰好是 777 的文件
find / -perm -u=s # 查找 SUID 文件
find / -perm -o=w # 所有用户可写的文件
find / -type f -perm /6000 # 找 SGID 或 SUID 的普通文件4.5 按类型搜索#
find . -type f # 只搜普通文件
find . -type d # 只搜目录
find . -type l # 只搜软链接4.6 搜索后执行操作#
# 删除 7 天前的日志(运维最常用)
find /app/logs -name "*.log" -mtime +7 -delete
# 搜索后执行自定义命令({} 代表找到的文件,\; 是命令结束符)
find /tmp -name "*.tmp" -exec rm -f {} \; # 每找到一个就起一个进程,文件多时慢
# -exec ... {} + 把多个文件拼进一条命令一次执行(等价于 xargs,快得多)
find /tmp -name "*.tmp" -exec rm -f {} +
# xargs:另一种批量方式。务必配 -print0 / -0,才能安全处理带空格、换行的文件名
find /tmp -name "*.tmp" -print0 | xargs -0 rm -f
# 搜索后改权限
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;
# 先确认再批量操作(安全做法)
find /app/logs -name "*.log" -mtime +7 -print # 先看看有哪些
find /app/logs -name "*.log" -mtime +7 -delete # 确认无误再删4.7 实战:清理 7 天前的日志#
# 场景:cron 加一条定时清理,防止磁盘被旧日志撑爆
# 先预览
find /var/log/myapp -name "*.log" -mtime +7 -print
# 确认后执行删除
find /var/log/myapp -name "*.log" -mtime +7 -delete
# 更精细:压缩而不是删除(适合需要保留的场景)
find /var/log/myapp -name "*.log" -mtime +7 -exec gzip {} \;
# 放入 crontab:每天凌晨 2 点清理
# 0 2 * * * find /var/log/myapp -name "*.log" -mtime +7 -delete5. 归档与压缩#
5.1 tar — 打包/解包#
tar 本身只打包不压缩,配合压缩参数后一步到位。
tar 核心参数#
| 参数 | 含义 | 记忆 |
|---|---|---|
c | Create 创建归档 | c = create |
x | eXtract 解包 | x = extract |
t | lisT 查看归档内容 | t = list |
v | Verbose 显示过程 | v = verbose |
f | File 指定文件名(必须放在最后) | f = file |
z | 通过 gzip 压缩/解压(.tar.gz) | z = gzip |
j | 通过 bzip2 压缩/解压(.tar.bz2) | j = bzip2 |
J | 通过 xz 压缩/解压(.tar.xz) | J = xz |
C | 解压到指定目录 | C = Change dir |
常用组合#
# 创建 gzip 压缩包(运维最常用)
tar czf archive.tar.gz /app/data/
# 查看包内容(不解压)
tar tzf archive.tar.gz
# 解包
tar xzf archive.tar.gz
# 解压到指定目录
tar xzf archive.tar.gz -C /opt/restore/
# 创建 bzip2 压缩包(压缩率更高但更慢)
tar cjf archive.tar.bz2 /app/data/
# 创建 xz 压缩包(压缩率最高)
tar cJf archive.tar.xz /app/data/
# 不解压,看包内文件列表
tar tzf archive.tar.gz | grep "\.log$"现代 tar 小抄:GNU tar(Rocky/Ubuntu 都是)解包时能自动识别压缩格式,
tar xf a.tar.gz、tar xf a.tar.xz不写z/j/J也能解。想用近年流行的 zstd(速度和压缩比俱佳):tar --zstd -cf a.tar.zst dir/。
# 打包但排除 .git 目录和 .log 文件
tar czf backup.tar.gz --exclude='.git' --exclude='*.log' /app/5.2 gzip / bzip2 / xz#
# gzip:压缩单个文件
gzip large_file.log # 生成 large_file.log.gz,原文件删除
gzip -k large_file.log # 保留原文件
# 解压
gunzip large_file.log.gz
gzip -d large_file.log.gz # 效果相同
# 查看压缩文件内容(不解压)
zcat large_file.log.gz # 相当于 gunzip -c | cat
zless large_file.log.gz # 分页查看压缩日志5.3 zip / unzip#
# 创建 zip(跨平台兼容好——发给 Windows 用户也能解)
zip -r backup.zip /app/data/
# 解压
unzip backup.zip
unzip -l backup.zip # 只看不拆5.4 实战:定时备份脚本#
#!/bin/bash
# 备份 /app/data 到 /backup/,自动带日期
BACKUP_DIR="/backup"
SOURCE="/app/data"
DATE=$(date +%Y%m%d_%H%M%S)
FILE="${BACKUP_DIR}/data_backup_${DATE}.tar.gz"
# 创建备份
tar czf "$FILE" "$SOURCE"
# 只保留最近 7 天的备份
find "$BACKUP_DIR" -name "data_backup_*.tar.gz" -mtime +7 -delete
echo "Backup completed: $FILE"5.5 rsync — 增量同步(比 cp 更实战)#
cp 每次都全量复制;rsync 只传输有变化的部分,是跨机备份、部署、镜像目录的首选。
# 本地目录同步(-a 归档保属性,-v 显示过程,-h 人类可读)
rsync -avh /app/data/ /backup/data/
# ⚠️ 结尾斜杠决定行为,最容易踩:
rsync -a /app/data /backup/ # data 目录本身放进 /backup/ → /backup/data/
rsync -a /app/data/ /backup/ # 只把 data 里的"内容"同步进 /backup/
# 跨机同步(走 SSH),-z 传输时压缩
rsync -avz -e ssh /app/data/ user@host:/backup/data/
# 镜像模式:让目标和源完全一致(会删掉源里已不存在的文件)
rsync -avh --delete /app/data/ /backup/data/
# 演练(dry-run):只显示会做什么、不真正动手——用 --delete 前务必先跑一遍
rsync -avhn --delete /app/data/ /backup/data/
# 大文件断点续传
rsync -avhP /app/big.img /backup/ # -P = --partial --progresscp vs rsync:一次性、小量复制用 cp;反复同步、跨机、大目录、要断点续传或增量,用 rsync。
6. 实战:文件夹比对(diff)#
# 比较两个文件
diff file1.txt file2.txt
# 比较两个目录
diff -r dir1/ dir2/
# 只看文件名差异
diff -qr dir1/ dir2/
# 用 vimdiff 可视化比较两个文件
vim -d config_old.yml config_new.yml7. 小结#
| 知识点 | 一句话记忆 |
|---|---|
| 查看 | ls -lah 看全貌,tree -L 2 看结构 |
| 复制 | 日常 cp -i 防覆盖,脚本 cp -a 保属性 |
| 删除 | rm -rf 不可逆,先 ls 或 find -print 确认再动手 |
| find | 名字/时间/大小/权限四种条件组合,-exec {} + 或 xargs -0 批量执行更快 |
| ln | ln 硬链接同 inode,ln -s 软链接存路径,重建软链用 ln -sfn |
| tar | c 创建 / x 解包 / t 查看,z 加 gzip;现代 tar 解包可省略压缩参数 |
| rsync | 增量同步,跨机/大目录首选,--delete 前先用 -n 演练 |
| diff | diff 看文件差异,vim -d 可视化对比 |