Ubuntu 系统系列 | 第 7 天:文件与文本操作——ls、cp、mv、find、grep、sed、awk 实战

第 7/30 天

引言

如果说终端是 Ubuntu 用户的驾驶舱,那么文件与文本操作命令就是方向盘和仪表盘。在 Linux 世界里,一切皆文件——普通文件、目录、设备、套接字、管道,统统以文件形式存在。掌握文件操作,就等于掌握了系统的命脉。

在前面的文章中,我们已经认识了 Shell 基础、用户权限和软件包管理。今天,我们将深入实战,系统学习七组最核心的文件与文本操作命令:ls、cp、mv、find、grep、sed、awk。这些命令是每一位 Linux 用户的必修课,无论你是桌面用户、开发者还是运维工程师,每天都会与它们打交道。

读完本文,你将能够:
– 用 ls 的数十种选项精准查看文件信息
– 用 cpmv 安全高效地复制、移动文件
– 用 find 快速定位任何文件
– 用 grep 在文件中搜索任意内容
– 用 sedawk 完成自动化文本处理

一、文件列表与查看:ls 的进阶用法

大部分人对 ls 的认知停留在 ls -l,但实际上它的能力远不止于此。

1.1 基础用法一览

# 最常用的组合
ls -lh              # 人性化大小显示(KB/MB/GB)
ls -la              # 显示所有文件(包括隐藏文件 .xxx)
ls -ltr             # 按时间倒序排列(最新文件在最后)
ls -lS              # 按文件大小排序
ls -R               # 递归显示子目录

# 输出示例
$ ls -lh /etc/ssh
total 624K
-rw-r--r-- 1 root root 581K Apr 22 10:23 moduli
-rw-r--r-- 1 root root 2.4K Apr 22 10:23 ssh_config
-rw------- 1 root root 4.3K Apr 22 10:23 sshd_config
drwxr-xr-x 2 root root 4.0K Apr 22 10:23 ssh_config.d

1.2 高级用法

# 显示文件 inode 编号(排查硬链接和文件系统问题时非常有用)
ls -li

# 按扩展名分类显示(在目录后加 /,可执行文件后加 *)
ls -lF

# 只显示目录本身
ls -ld /etc/ssh/

# 显示文件类型(FIFO、socket、符号链接一目了然)
ls -l --file-type

# 自定义时间格式
ls -l --time-style=long-iso

# 输出示例(-li 组合)
$ ls -li /etc/ | head -5
 131073 drwxr-xr-x   3 root root  4096 Jul 19 08:00 acpi
 131074 -rw-r--r--   1 root root  3028 Apr 22  2024 adduser.conf
 131075 drwxr-xr-x   2 root root  4096 Jul 19 08:08 alternatives
 131076 drwxr-xr-x   6 root root  4096 Apr 22  2024 apache2
 131077 drwxr-xr-x   3 root root  4096 Jul 19 08:00 apparmor

💡 小技巧ll 通常是 ls -alF 的别名,在 Ubuntu 中默认已配置。你也可以用 alias ls='ls --color=auto' 让文件和目录以不同颜色区分显示。

二、文件复制与移动:cp 和 mv 的安全姿势

2.1 cp:复制文件

# 基本用法
cp source.txt dest.txt           # 复制文件
cp -r source_dir/ dest_dir/      # 递归复制目录
cp -i source.txt dest.txt        # 交互模式(覆盖前询问)
cp -u source.txt dest.txt        # 仅在源文件更新时复制(增量备份利器)
cp -p source.txt dest.txt        # 保留文件属性(权限、时间戳)
cp -v source.txt dest.txt        # 显示复制过程

# 安全复制的最佳实践
cp -ivp source.txt /backup/      # 交互 + 显示 + 保留属性

# 批量复制
cp /etc/apt/sources.list.d/*.sources /backup/apt-sources/
cp -r /var/log/{syslog,dmesg,kern.log} /tmp/logs/  # 花括号展开

2.2 mv:移动与重命名

# 基本用法
mv file.txt /tmp/                # 移动文件到 /tmp
mv oldname.txt newname.txt       # 重命名文件(同一目录下)
mv -i file.txt /tmp/             # 交互模式
mv -u file.txt /tmp/             # 仅当目标不存在或更旧时移动
mv -v file.txt /tmp/             # 显示过程

# 批量重命名妙用
# 使用循环批量添加后缀
for f in *.log; do mv "$f" "${f%.log}.bak"; done

# 使用 rename 命令(更强大)
rename 's/.JPG$/.jpg/' *.JPG   # 统一文件扩展名大小写

2.3 安全红线

# ⚠️ 危险操作示例——千万不要这样用
cp -f /etc/passwd /etc/shadow    # 用 passwd 覆盖 shadow → 系统崩溃
mv /etc /tmp                     # 移动 /etc 目录 → 系统瘫痪
rm -rf /                         # 不用解释了

# ✅ 安全做法
cp -ivp /etc/nginx/nginx.conf /tmp/backup/  # 加 -i 确认
alias cp='cp -i'                 # 在 ~/.bashrc 中设置别名,防止误覆盖
alias mv='mv -i'                 # 同理

三、文件查找:find 命令全方位指南

find 是 Linux 中最强大的文件搜索工具,没有之一。它比任何 GUI 搜索工具都快、都灵活。

3.1 按名称查找

# 按文件名查找
find /etc -name "*.conf"                    # 查找所有 .conf 文件
find / -name "nginx.conf"                   # 全盘查找
find /home -iname "readme.txt"              # 忽略大小写
find . -name "*.log" -type f                # 只查找普通文件,不包含目录

# 通配符模式
find /var/log -name "syslog*"               # 模糊匹配
find /etc -name "*.d" -type d               # 查找所有以 .d 结尾的目录

3.2 按类型和大小查找

# 按类型
find / -type f                               # 普通文件
find / -type d                               # 目录
find / -type l                               # 符号链接
find / -type s                               # 套接字文件
find / -type b                               # 块设备

# 按大小
find /var -size +100M                        # 大于 100MB 的文件
find /var -size -1M                          # 小于 1MB 的文件
find / -size +1G -type f                     # 大于 1GB 的普通文件
find . -size 1024c                           # 正好 1024 字节的文件

# 实战:查找磁盘空间占用大户
find / -xdev -type f -size +500M -exec ls -lh {} ; 2>/dev/null | sort -k5 -hr

3.3 按时间查找

# 按修改时间
find /etc -mtime -7                          # 最近 7 天内修改过的文件
find /var/log -mtime +30                     # 30 天前修改的文件(旧日志)
find . -mmin -60                             # 最近 60 分钟内修改的文件

# 按访问时间
find /home -atime -3                         # 最近 3 天访问过的文件

# 按权限变化时间
find /etc -ctime -1                          # 最近 1 天权限或属性变更的文件

3.4 按权限和所有者查找

# 按权限
find / -perm 4000 -type f                    # 查找 SUID 文件(安全隐患!)
find / -perm -2000 -type f                   # 查找 SGID 文件
find /home -perm 777 -type f                 # 查找权限过于开放的文件
find / -nouser -o -nogroup                   # 查找孤立的文件(无属主或属组)

# 按所有者
find /home -user zhangsan                    # 查找属于某个用户的文件
find /var -group www-data                    # 查找属于某个组的文件

3.5 对查找结果执行操作

# 查找到后删除
find /var/log -name "*.log" -mtime +30 -delete  # 删除 30 天前的日志

# 查找到后执行命令(-exec 是核心功能)
find . -name "*.py" -exec wc -l {} ;        # 统计所有 Python 文件的行数
find /tmp -mtime +7 -exec rm -f {} ;        # 删除 7 天前的临时文件
find . -name "*.sh" -exec chmod +x {} ;     # 给所有 shell 脚本加执行权限

# 更高效的 + 号(批量执行,减少进程数)
find . -name "*.log" -exec rm -f {} +        # 一次 rm 处理多个文件,比 ; 快

# 实战:批量替换文件内容
find . -name "*.html" -exec sed -i 's/oldtext/newtext/g' {} ;

📌 注意-delete 操作很危险,务必先用 -name 命令确认查找结果。建议先不加 -delete 运行一次,确认结果正确后再加。

四、文本搜索:grep 全面掌握

grep 是文本搜索的瑞士军刀,从日志分析到代码检索,无处不在。

4.1 基础用法

# 在文件中搜索
grep "error" /var/log/syslog                 # 在 syslog 中搜索 "error"
grep -i "error" /var/log/syslog              # 忽略大小写
grep -n "error" /var/log/syslog              # 显示行号
grep -c "error" /var/log/syslog              # 只统计匹配行数
grep -v "error" /var/log/syslog              # 反向匹配(不含 error 的行)

# 输出示例
$ grep -n "Listen" /etc/ssh/sshd_config
13:#Port 22
15:#AddressFamily any
17:#ListenAddress 0.0.0.0
19:#ListenAddress ::

4.2 正则表达式搜索

# 扩展正则(-E 或 egrep)
grep -E "^[0-9]{3,5}" /etc/services          # 匹配 3-5 位数字开头的行
grep -E "(error|fatal|panic)" /var/log/app.log  # 匹配多个关键词
grep -E "192.168.d{1,3}.d{1,3}" /var/log/auth.log  # 匹配 IP 地址

# 正则符号速查
# ^      行首
# $      行尾
# .      任意单个字符
# *      前一个字符重复 0 次或多次
# +      前一个字符重复 1 次或多次
# []     字符集,匹配其中任意一个
# [^]    否定字符集
# |     或
# {n}  精确重复 n 次

4.3 实战场景

# 日志分析
grep -r "ERROR" /var/log/ --include="*.log"  # 递归搜索所有 .log 文件
grep -A5 "FATAL" app.log                     # 显示匹配行及其后 5 行
grep -B5 "FATAL" app.log                     # 显示匹配行及其前 5 行
grep -C5 "FATAL" app.log                     # 显示匹配行及其前后各 5 行

# 代码搜索
grep -rn "function " /usr/src/ --include="*.js"  # 搜索 JavaScript 函数定义
grep -rn "^def " /usr/src/ --include="*.py"      # 搜索 Python 函数定义

# 进程过滤
ps aux | grep nginx                          # 查找 nginx 进程
ps aux | grep -v grep | grep nginx           # 排除 grep 自身(更干净)

# 统计并排序
grep -o "GET|POST|PUT|DELETE" access.log | sort | uniq -c | sort -rn
# 输出示例:
# 15234 GET
#  2341 POST
#   892 PUT
#    45 DELETE

五、流编辑器:sed 实战

sed(Stream Editor)是非交互式文本处理工具,常用于批量替换、删除、插入操作。

5.1 替换操作

# 基础替换
sed 's/old/new/' file.txt                    # 替换每行第一个匹配
sed 's/old/new/g' file.txt                   # 全局替换(所有匹配)
sed 's/old/new/gi' file.txt                  # 全局替换 + 忽略大小写
sed 's/old/new/2' file.txt                   # 只替换每行第二个匹配

# 指定行号
sed '3s/old/new/' file.txt                   # 只替换第 3 行
sed '1,5s/old/new/g' file.txt               # 替换第 1-5 行
sed '/^$/d' file.txt                         # 删除所有空行

# 实际操作演示
$ echo "Hello World, hello Linux" | sed 's/hello/hi/gI'
Hi World, hi Linux

# 原地修改文件(-i 选项)
sed -i 's/192.168.1.100/192.168.1.200/g' /etc/nginx/nginx.conf  # 批量替换 IP

# 备份原文件
sed -i.bak 's/192.168.1.100/192.168.1.200/g' /etc/nginx/nginx.conf
# 会生成 nginx.conf.bak 备份文件

5.2 删除和插入

# 删除行
sed '5d' file.txt                            # 删除第 5 行
sed '1,10d' file.txt                         # 删除第 1-10 行
sed '/^#/d' /etc/ssh/ssh_config              # 删除所有注释行(以 # 开头)
sed '/^$/d' /etc/ssh/ssh_config              # 删除所有空行

# 组合:删除注释和空行
sed -e '/^#/d' -e '/^$/d' file.txt

# 插入行
sed '3iThis is a new line' file.txt         # 在第 3 行前插入
sed '3aThis is a new line' file.txt         # 在第 3 行后追加
sed '$a# End of file' file.txt              # 在文件末尾追加

# 实战:给 nginx 配置添加新 server
sed -i '/^http {/a    server_names_hash_bucket_size 128;' /etc/nginx/nginx.conf

5.3 多命令组合

# 使用 -e 连接多个命令
sed -e 's/foo/bar/g' -e 's/baz/qux/g' -e '/^#/d' file.txt

# 使用分号分隔
sed 's/foo/bar/g; s/baz/qux/g; /^#/d' file.txt

# 使用脚本文件
cat > /tmp/cleanup.sed << 'EOF'
s/^[[:space:]]*//     # 去掉行首空格
s/[[:space:]]*$//     # 去掉行尾空格
/^$/d                 # 删除空行
s/  */ /g             # 多个空格合并为一个
EOF
sed -f /tmp/cleanup.sed messy.txt > clean.txt

六、文本分析利器:awk

awk 是 Linux 上最强大的文本处理工具之一,它不仅可以搜索和替换,还能进行格式化、统计和报表生成。

6.1 基础字段提取

# 默认按空格/制表符分割
awk '{print $1}' file.txt                    # 打印第一列
awk '{print $1, $3}' file.txt                # 打印第一和第三列
awk '{print $NF}' file.txt                   # 打印最后一列
awk '{print NR, $0}' file.txt                # 打印行号 + 整行

# 实际操作(查看磁盘使用情况)
$ df -h | awk '{print $1, $5, $6}'
Filesystem Use% Mounted
/dev/sda3 45% /
/dev/sda1 12% /boot
tmpfs 0% /dev/shm

6.2 条件过滤

# 使用条件表达式
awk '$5 > 80 {print $1, $5}' disk.txt       # 打印使用率超过 80% 的分区
awk '/ERROR/ {print NR, $0}' /var/log/syslog  # 打印包含 ERROR 的行及其行号
awk 'NR >= 10 && NR <= 20' file.txt          # 打印第 10-20 行

# 实战:找出最耗 CPU 的进程
ps aux | awk '$3 > 1.0 {print $11, $3"%"}' | sort -k2 -rn | head -10
# 输出示例:
# /usr/bin/python3 15.2%
# /usr/bin/gnome-shell 8.7%
# /usr/sbin/nginx 3.1%

6.3 内置变量和函数

# 常用内置变量
# NR    当前行号
# NF    当前行字段数
# $0    整行
# $1-$N 第 1 到 N 个字段
# FS    字段分隔符(默认空格/制表符)
# OFS   输出字段分隔符(默认空格)

# 使用自定义分隔符
awk -F: '{print $1, $3}' /etc/passwd | head -3
# 输出:
# root 0
# daemon 1
# bin 2

# 更复杂的格式化输出
awk -F: 'BEGIN {printf "%-20s %-10s %-10sn", "用户", "UID", "Shell"} 
         {printf "%-20s %-10s %-10sn", $1, $3, $7}' /etc/passwd | head -5
# 输出:
# 用户                    UID        Shell
# root                    0          /bin/bash
# daemon                  1          /usr/sbin/nologin
# bin                     2          /usr/sbin/nologin

6.4 统计与汇总

# 统计日志中各状态码数量
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 输出示例:
#   15432 200
#    2341 304
#     892 404
#      45 500

# 计算平均值
awk '{sum += $1} END {print "平均:", sum/NR}' numbers.txt

# 统计各 IP 访问次数
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# 输出示例:
#   4321 192.168.1.100
#   2110 10.0.0.55
#    987 203.0.113.42

七、命令组合实战

将多个命令通过管道组合,可以完成复杂的文件处理任务。

7.1 日志分析实战

# 统计今天各小时的错误数
grep "$(date +%Y-%m-%d)" /var/log/syslog | 
  grep -i "error" | 
  awk '{print $3}' | 
  cut -d: -f1 | 
  sort | uniq -c | sort -rn
# 输出示例:
#   23 10
#   18 09
#   12 08
#    5 07

# 查找最大的 10 个日志文件
find /var/log -name "*.log" -type f -exec ls -lh {} ; | 
  awk '{print $5, $NF}' | 
  sort -hr | head -10

7.2 系统巡检组合

# 一键生成系统报告
echo "=== 系统信息 ==="
uname -a
echo ""
echo "=== 磁盘使用率超过 80% 的分区 ==="
df -h | awk 'NR>1 && $5+0 > 80 {print $0}'
echo ""
echo "=== 内存占用 TOP 10 进程 ==="
ps aux --sort=-%mem | head -11
echo ""
echo "=== 最近登录记录 ==="
last -10
echo ""
echo "=== 最近修改的配置文件 ==="
find /etc -name "*.conf" -mtime -1 -type f 2>/dev/null

7.3 文件批量处理

# 批量重命名:将 .txt 改为 .md
find . -name "*.txt" -exec bash -c 'mv "$0" "${0%.txt}.md"' {} ;

# 批量替换文件中的域名
find /etc/nginx -name "*.conf" -exec sed -i 's/old-domain.com/new-domain.com/g' {} ;

# 批量压缩旧日志
find /var/log -name "*.log" -mtime +7 -exec gzip {} ;

常见问题与最佳实践

Q1: ls 显示文件但实际不存在(符号链接损坏)

原因:符号链接指向的目标文件已被删除。

解决方案

# 查找所有损坏的符号链接
find / -type l ! -exec test -e {} ; -print 2>/dev/null

# 删除损坏的链接
find / -type l ! -exec test -e {} ; -delete 2>/dev/null

Q2: find 命令执行慢或无响应

原因:搜索范围过大,或包含大量文件(如 /proc、/sys 虚拟文件系统)。

解决方案

# 使用 -xdev 限制在同一文件系统内(不跨挂载点)
find / -xdev -name "*.conf"

# 排除特定目录
find / -name "*.log" -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null

# 限制搜索深度
find / -maxdepth 3 -name "*.conf"

Q3: grep 搜索结果太多,如何精简

解决方案

# 只显示文件名
grep -rl "error" /var/log/

# 只显示匹配次数
grep -c "error" /var/log/*.log

# 先过滤再搜索
grep "2026-07-21" /var/log/syslog | grep -i "error"

Q4: sed 替换后文件内容消失

原因-i 直接修改了原文件,且替换模式匹配到了不该匹配的内容。

解决方案

# 始终使用 -i.bak 备份
sed -i.bak 's/pattern/replacement/g' important.conf

# 先测试,不修改文件
sed 's/pattern/replacement/g' important.conf | head -20

# 使用 diff 确认修改
diff important.conf.bak important.conf

总结

今天深入学习了七组核心文件与文本操作命令:

命令 核心用途 推荐组合
ls 文件列表查看 -lh-la-ltr
cp/mv 复制、移动、重命名 始终加 -i 防误操作
find 文件搜索定位 -name-type-exec
grep 文本内容搜索 -rn-i-C5、正则
sed 流式文本替换 -i.baks/old/new/g
awk 字段提取与统计 -F{print $N}BEGIN/END

这些命令的威力在于组合使用。一个 find + grep + awk 的管道链,就能完成传统 GUI 工具无法企及的复杂任务。

下期预告: 第 8 天我们将进入系统管理的核心领域——系统服务管理,深入理解 systemd 和 systemctl 的方方面面,从服务启停到自定义单元文件,再到开机自启和故障排查,让你对 Ubuntu 的服务管理体系了如指掌。


📖 系列目录

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容