本文以 Bash 风格语法为主;Fish 的变量、命令替换、历史与配置语法有差异。
前三篇是"用什么命令",这篇是"怎么把命令串起来"。管道和重定向是 Linux 哲学的具象化:小工具组合出大威力。
管道#
| — 把一个命令的输出喂给下一个命令
command1 | command2本质:command1 的标准输出 直接变成 command2 的标准输入。
ps aux | grep python # ps 的输出交给 grep 筛选
ls -l | wc -l # 统计显示行数,含 total 行;不是可靠文件数
cat file.txt | grep error # 等价于 grep error file.txt
du -sh * | sort -hr # 列出文件大小,从大到小排管道可以一直串下去:
cat access.log | grep "404" | cut -d' ' -f1 | sort | uniq -c | sort -rn
# 解释:日志 → 筛404 → 取IP列 → 排序 → 去重计数 → 按次数倒排
# 结果:谁在疯狂 404 一目了然重定向#
> — 输出到文件(覆盖)
echo "hello" > file.txt # 写内容到文件,覆盖原有内容
ls -la > listing.txt # ls 的结果存到文件,终端不显示>> — 输出到文件(追加)
echo "another line" >> file.txt # 追加到末尾< — 从文件读取输入
wc -l < file.txt # 把文件内容喂给 wc(等价于 wc -l file.txt)2>&1 — 把错误输出合并到标准输出
./script.sh > output.log 2>&1 # 正常输出和报错都进同一个文件
./script.sh > /dev/null 2>&1 # 静默运行,什么都不显示理解模型:
| 编号 | 名字 | 默认去向 |
|---|---|---|
| 0 | stdin(标准输入) | 键盘 |
| 1 | stdout(标准输出) | 终端 |
| 2 | stderr(标准错误) | 终端 |
2>&1 的意思是:把 stderr(2)重定向到 stdout(1)去的地方。
通配符#
* # 匹配任意多个字符
? # 匹配恰好一个字符
[abc] # 匹配 a、b、c 中的任意一个
[0-9] # 匹配 0-9 任意数字ls *.md # 所有 .md 文件
ls report_??.txt # 先预览任意两个字符后缀(不限定数字)
rm -- report_??.txt # 核对列表后才删除;不匹配时的行为取决于 Shell
ls [A-Z]*.md # 大写字母开头的 .md 文件变量#
定义和使用
name="hello" # 定义变量,等号两边不能有空格
echo "$name" # 使用变量,加 $ 前缀
echo "${name}" # 也可以用花括号包起来环境变量
echo $PATH # 可执行文件的搜索路径
echo $HOME # 你的家目录
echo $USER # 当前用户名
env # 列出所有环境变量
export MY_VAR="val" # 设为环境变量(子进程可见)命令替换
now=$(date) # 把 date 命令的输出赋给变量
echo "现在时间:$now"
files=$(find . -maxdepth 1 -type f -printf 'x\n' | wc -l) # GNU find:当前目录普通文件数别名#
alias — 给长命令起短名
alias ll='ls -lah' # ll 代替 ls -lah
alias gs='git status' # git 常用操作缩到两字母
alias ..='cd ..' # 快速回上级
alias # 查看当前所有别名永久生效需要写到 ~/.bashrc(bash)或 ~/.config/fish/config.fish(fish)。
历史与快捷操作#
history — 查看命令历史
history # 全部历史
history | grep git # 在历史中搜 git 相关命令复用历史命令
!! # 重复上一条命令
!git # 重复最近一条以 git 开头的命令
!$ # 上一条命令的最后一个参数终端快捷键
| 快捷键 | 作用 |
|---|---|
Ctrl+C |
终止当前前台程序 |
Ctrl+Z |
暂停当前前台程序 |
Ctrl+D |
发送 EOF(退出终端/关闭输入流) |
Ctrl+L |
清屏(等价于 clear) |
Ctrl+R |
反向搜索历史命令 |
Ctrl+A |
光标跳到行首 |
Ctrl+E |
光标跳到行尾 |
Ctrl+W |
删除光标前一个词 |
Ctrl+U |
删除光标前全部内容 |
Ctrl+R 特别实用:在长历史里搜索用过的命令,再按一次继续往前搜。
组合示例#
一行命令解决实际问题
# 当前目录项目(含目录)的磁盘占用前 5 名
du -sh * | sort -hr | head -5
# 统计名称匹配的进程数(不是线程数)
pgrep -c nginx
# 查看已知 PID 的线程数与线程列表
ps -o nlwp= -p PID
ps -T -p PID
# 查看 8080 端口被哪个程序占了
ss -tlnp | grep 8080
# 递归找所有 .md 文件中有多少行包含 "TODO"
grep -rn --include="*.md" "TODO" . | wc -l这就是 Unix 哲学:每个命令做好一件事,用管道把它们串起来。
核心心智模型#
输入(stdin) → [命令] → 输出(stdout)
↓
错误(stderr)
管道 | :把 A 的 stdout 给 B 的 stdin
重定向 > :把 stdout 存到文件
2>&1 :把 stderr 合并到 stdout 同一去处理解了这个,所有命令的拼接方式都自然想通了。
重定向从左到右处理:> output.log 2>&1 与 2>&1 > output.log 不等价。!! 等历史展开在交互 Bash 中可用,执行前应核对展开后的命令。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。