OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 042

Shell 基本功

用管道、重定向、变量和历史操作组合命令行工具。

所在专题Linux 命令行基础与组合 ↗
约 7 分钟阅读开始阅读

本文以 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 中可用,执行前应核对展开后的命令。

参考与延伸

  1. GNU Bash 手册 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Linux 命令行基础与组合

  1. 01文件与目录操作
  2. 02进程与作业管理
  3. 03文本处理与系统查询
  4. 04Shell 基本功
  5. 05模糊搜索:fzf
  6. 06参数传递:xargs
CONTINUE READING / 下一篇模糊搜索:fzf

把文件、进程、分支和历史列表变成可交互选择的输入。