前言本文档旨在记录观看 MIT Missing Semester 课程时的核心笔记,涵盖 Shell 基础概念、常用命令、现代替代工具与 Shell 编程。
1. Shell 概述
1.1 什么是 Shell?
Shell 是位于操作系统内核与用户之间的外围薄层程序。它为用户提供了一个直接访问系统功能的接口,允许用户通过文本命令与操作系统进行交互。Shell 通常以命令行界面 (CLI) 的形式存在。
1.2 如何启动?
- Linux: 按下
Ctrl+Alt+T。 - macOS: 按下
Cmd+Space,搜索 “Terminal” 并打开。 - Windows: 建议安装并使用 适用于 Linux 的 Windows 子系统 (WSL),或使用 Linux 虚拟机。
2. 基础命令
2.1 echo
echo 是一个基础命令,用于将参数文本输出到标准输出(通常是终端屏幕),或将其重定向到文件中。
基本语法:
echo [选项] <字符串>2.1.1 直接输出字符串
echo Hello, Shell!# 或echo "Hello, Shell!"# 输出: Hello, Shell!2.1.2 常用选项 (Options)
-n:禁止在输出末尾自动换行。-e:启用反斜杠转义字符的解释(在 Linux/GNU 环境下通常默认开启)。
2.1.3 高级用法
A. 变量替换
echo 会自动展开环境变量和 Shell 变量:
NAME="Alice"echo "Hello, $NAME"# 输出: Hello, AliceB. 命令替换
echo 可以输出其他命令的执行结果:
echo "Current date is: $(date)"# 输出示例: Current date is: Tue Mar 10 19:54:54 CST 2026# 注:具体时间取决于命令执行时的系统时间。C. 重定向到文件
echo 常用于创建文件或向文件追加内容:
-
覆盖写入 (
>):若文件存在则清空后重写;若不存在则创建。Terminal window echo "First line" > file.txt -
追加写入 (
>>):在文件末尾添加内容,保留原有内容。Terminal window echo "Second line" >> file.txt -
创建空文件:
Terminal window echo -n > emptyfile.txt
D. 输出特殊字符
若需输出 $、! 等特殊字符且不被 Shell 解释,请使用单引号:
echo 'Price is $100'# 输出: Price is $1002.2 cd
cd (Change Directory) 用于改变当前工作目录。
2.2.1 相对路径与绝对路径
- 相对路径:基于当前目录的位置。
- 示例:
cd projects/missing-semester(假设当前位于/home/ssj)。 - 适用场景:在当前目录附近移动时更为便捷。
- 示例:
- 绝对路径:从根目录
/开始的完整路径。- 示例:
cd /home/ssj/projects/missing-semester。 - 适用场景:需要从深层子目录跳转至完全无关的其他目录时。
- 示例:
2.2.2 快速切换目录 (cd -)
利用 cd - 可在最近两个访问过的目录间快速切换。
$ cd /var/log # 进入日志目录$ cd /etc/nginx # 进入配置目录$ cd - # 瞬间返回 /var/log$ cd - # 再次瞬间返回 /etc/nginx2.2.3 其他基础用法
| 命令 | 功能 | 解释 |
|---|---|---|
cd .. | 返回上一级目录 | .. 代表父目录。例如在 /home/user/docs 执行后变为 /home/user。 可叠加使用,如 cd ../.. 返回上两级。 |
cd . | 留在当前目录 | . 代表当前目录。通常用作占位符或脚本中的空操作。 |
cd 或 cd ~ | 回到 Home 目录 | 直接输入 cd 等价于 cd ~,将返回当前用户的家目录(如 /home/ssj)。 |
2.2.4 利用 Tab 键自动补全
Shell 支持通过 Tab 键自动补全路径,提高效率。
- 操作:输入
cd Doc后按下Tab键。 - 效果:若目录下唯一匹配项为
Documents,Shell 会自动补全为cd Documents/。 - 多匹配项:若存在多个匹配项,连续按两次
Tab将显示所有可选列表。
2.3 man & tldr
当遗忘命令的具体用法或参数时,可使用以下两种工具:传统的 man (Manual Pages) 与现代社区驱动的 tldr (Too Long; Didn’t Read)。
2.3.1 man (手册页)
- 常见用法:
man <command>:查看指定命令的详细手册。/keyword:在手册中搜索关键词(按n查找下一个匹配项,按q退出)。
2.3.2 tldr (简化手册)
tldr 是一个开源社区项目,旨在提供精简的、基于示例的命令帮助页面。对于复杂命令(如 tar, ffmpeg, git),man 手册往往篇幅过长,而 tldr 则更加直观实用。
- 常见用法:
tldr <command>:查看指定命令的简化帮助页及常用示例。tldr --update:从 GitHub 拉取最新的社区贡献页面以更新本地缓存。tldr --random:随机显示一个命令的用法,适合碎片化学习。
2.4 ls
ls (List) 用于列出目录内容。
ls:默认列出当前目录下的非隐藏文件和文件夹。ls -a(All):列出所有文件,包括以.开头的隐藏文件(如.bashrc,.git)。ls -A:列出隐藏文件,但排除.(当前目录) 和..(上级目录)。
ls <PATH>:列出指定路径下的所有内容。
2.5 which
which 命令用于在系统的 PATH 环境变量指定的目录中查找并返回指定可执行文件的完整路径。
-
基本用法:
/usr/sbin/date which <command_name># 示例:$ which date -
查找所有匹配项:
Terminal window which -a <command_name># 示例:$ which -a sh# 输出:# /home/jon/.nix-profile/bin/sh# /run/current-system/sw/bin/sh
2.6 cat & bat
2.6.1 cat
cat (Catenate) 是 Linux/Unix 的标准命令,用于查看文件内容、连接文件或重定向输出。其功能简单直接,但输出无格式高亮。
- 用法:
cat <file>
2.6.2 bat (现代替代品)
bat (常被称为 batcat) 是 cat 的现代化增强版,主要特性包括:
- 语法高亮:支持多种编程语言。
- 行号显示:自动显示行号。
- 自动分页:长文件自动调用分页器(类似
less)。 - Git 集成:侧边栏显示 Git 修改状态。
- 主题定制:支持多种颜色主题。
- 用法:
bat <file>
其他相关命令
sort <file>:将文件内容按行排序后输出。uniq <file>:移除文件中连续的重复行(通常需先排序)。head <file>:查看文件开头(默认前 10 行)。head -n 20 <file>:查看前 20 行。
tail <file>:查看文件结尾(默认后 10 行)。tail -f <file>:实时追踪文件的新增内容,查看日志文件时的必备工具。
2.7 grep
grep 用于在文件中按指定模式(正则表达式)搜索并匹配内容。
-
基本用法:
grep [选项] <pattern> <file> -
常用参数:
-r:递归搜索目录。-i:忽略大小写。-v:反向匹配(显示不包含该模式的行)。-E:使用扩展正则表达式。-l:仅打印匹配的文件名。-c:仅打印匹配的行数。
-
示例:
Terminal window grep "ERROR" logfile.txt# 在 logfile.txt 中搜索包含 "ERROR" 的行并完整打印。
💡 现代工具推荐:ripgrep(rg)比
grep速度更快,默认忽略.gitignore中的文件,默认递归搜索,用户体验更佳。
2.8 find
find 用于按指定条件在目录树中查找文件。
-
基本用法:
find <path> [条件] -
常用条件:
-name "*.py":按文件名匹配。-type f:仅查找普通文件(排除目录)。-mtime +30:查找 30 天前被修改过的文件。-size +100M:查找大于 100 MB 的文件。-exec <cmd> {} \;:对找到的每个文件执行指定命令。
-
示例:
Terminal window find . -name "*.log" -mtime +7 -exec rm {} \;# 删除当前目录及其子目录下 7 天前修改过的 .log 文件。
💡 现代工具推荐:fd
find的现代替代品。默认彩色输出,默认忽略隐藏文件和.gitignore,语法更简洁(例如fd pattern等同于find . -name '*pattern*')。
2.9 sed
sed (Stream Editor) 是一款流编辑器,常用于对文件内容进行筛选、替换等操作。
- 基本用法:
sed [选项] '脚本' <file> - 常用参数与指令:
-i:直接修改文件内容(In-place)。-n/--quiet/--silent:仅显示经脚本处理后的行(配合p指令使用)。s:替换指令 (Substitution)。g:全局替换标志(否则每行仅替换第一个匹配项)。p:打印指令,通常与-n连用以输出特定行。
- 示例:
-
全局替换:
Terminal window sed 's/old/new/g' <file># 将文件中所有的 "old" 替换为 "new" 并输出结果。 -
打印特定行:
Terminal window sed -n '10,20p' <file># 仅打印文件的第 10 到 20 行。
-
2.10 awk
awk 是一种强大的文本分析与数据提取语言,支持数学运算、变量定义及 BEGIN/END 块处理。
- 基本用法:
awk [选项] '模式 {动作}' <file> - 用法示例:
-
打印第二列:
Terminal window awk '{print $2}' file -
指定分隔符(如 CSV 文件):
Terminal window awk -F',' '{print $2}' file.csv# 以逗号为分隔符,打印第二列。 -
条件逻辑:
Terminal window awk '$2 > 100 {print $1}' file# 仅当第二列数值大于 100 时,打印第一列。
-
3. Shell 编程
3.1 管道 (Pipes |)
管道|,它将前一个命令的标准输出 (stdout) 直接作为后一个命令的标准输入 (stdin)。
-
用法示例:
Terminal window # 统计当前目录下出现频率最高的5个文件扩展名find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -n 5# 解析 SSH 日志,提取断开连接的用户名并统计 Top 10ssh myserver 'journalctl -u sshd -b-1 | grep "Disconnected from"' \| sed -E 's/.*Disconnected from .* user (.*) [^ ]+ port.*/\1/' \| sort | uniq -c \| sort -nk1,1 | tail -n10 \| awk '{print $2}' | paste -sd,
3.2 重定向 (Redirections)
> file: 将 stdout 写入文件(覆盖)。>> file: 将 stdout 追加到文件。< file: 从文件读取 stdin。2> file: 将 stderr (错误输出) 写入文件。&> file或> file 2>&1: 将 stdout 和 stderr 都写入同一文件。tee命令: 既将输出打印到屏幕,又写入文件。- 用法:
verbose_command | tee log.txt | grep "ERROR"(既能看日志又能存盘还能过滤)。
- 用法:
3.3 控制流与脚本
Shell 是一门完整的编程语言,支持变量、循环和条件判断。
-
条件判断:
Terminal window if [ -f "config.txt" ]; thenecho "File exists"elseecho "File missing"fi# 推荐使用 [[ ]] 而非 [ ],因为它更安全且支持更多特性if [[ "$var" == "hello" ]]; then …; fi -
循环:
-
For 循环:
Terminal window # 遍历文件for file in *.txt; doecho "Processing $file"done# 命令替换生成序列for i in $(seq 1 5); doecho "Iteration $i"done -
While 循环:
Terminal window while [[ condition ]]; do# 执行操作sleep 1done
-
-
编写一个健壮的脚本:
在脚本开头加入set标志以避免常见错误:#!/bin/bashset -euo pipefail# -e: 任何命令失败立即退出脚本# -u: 使用未定义变量时报错# -o pipefail: 管道中任何命令失败视为整个管道失败 -
后台运行:
command &: 在后台运行命令。$!: 获取最后一个后台进程的 PID。kill $PID: 终止进程。