本文档介绍 CS 领域常用工具,核心内容参考自 MIT 课程 The Missing Semester of Your CS Education

相关阅读与扩展链接:


Shell

Bash

参考资料:

核心概念与语法

  • Shebang:声明脚本解释器,位于文件首行(如 #!/usr/bin/env bash#!/usr/bin/env python)。建议使用 env 以自动在 PATH 环境变量中搜索对应解释器。
  • 变量赋值:格式为 foo=bar注意:等号前后严禁有空格。
  • 字符串解析
    • 双引号 "" 会解析并替换内部变量(如 echo "$foo" 输出 bar)。
    • 单引号 '' 则保持内部所有字符的字面本义。
  • 返回值:脚本执行结束会返回状态码,0 表示正常/成功。
  • 条件判断:执行高级比较操作时推荐使用 [[ ]](参考 test(1) - Linux manual page)。
  • 命令替换与进程替换
    • Command Substitution:执行命令并将其输出作为变量提取,格式为 for file in $(ls)
    • Process Substitution:执行命令并将输出保存至临时文件描述符,再返回该路径,格式为 <(CMD)

通配符 (Wildcards)

符号说明示例
?匹配单个字符-
*匹配任意数量的字符-
[]匹配括号内的任意单个字符-
{}自动展开括号内的所有组合{a,b}/c 展开为 a/c b/c
..生成连续序列{1..3} 展开为 1 2 3

多命令控制流

语法逻辑描述
CMD1; CMD2顺序执行:无视 CMD1 的返回值,按顺序执行。
CMD1 && CMD2逻辑与:仅当 CMD1 正确执行(返回 0)时,才执行 CMD2
CMD1 || CMD2逻辑或:仅当 CMD1 执行失败时,才执行 CMD2
CMD1 | CMD2管道操作:将 CMD1 的标准输出作为 CMD2 的标准输入。

特殊变量与字符

变量/字符含义
$0当前执行的脚本名称。
$1 - $9传递给脚本的第 1 到第 9 个位置参数。
$@传递给脚本的所有参数集合。
$#传递给脚本的参数总数。
$?前一条命令的退出状态码。
$$当前脚本执行的进程 PID。
!!快速重复执行上一条命令(常用于 sudo !! 提权)。
$_上一条命令的最后一个参数(交互式 Shell 中可用 Esc + . 快捷键提取)。

终端快捷键

光标移动与编辑

  • Ctrl + a / Ctrl + e:移动光标至行首 / 行尾。
  • Alt + f / Alt + b:按单词向前(右) / 向后(左)跳跃。
  • Ctrl + u / Ctrl + k:清空当前整行 / 删除光标至行尾的全部内容。
  • Alt + Backspace / Alt +d:删除光标至单词开头 / 单词结尾的内容。
  • Ctrl + c:终止当前正在输入或运行的命令。

任务控制在 Shell 中,终端窗口与当前运行的会话进程强绑定。

  • Ctrl + c:向进程发送 SIGINT 信号(请求中断,进程不一定立即停止)。
  • Ctrl + *:向进程发送 SIGQUIT 信号(强制终止进程并生成核心转储)。
  • Ctrl + z:向进程发送 SIGSTOP 信号(挂起/暂停进程,将其放入后台)。
  • 关闭终端窗口:等同于向进程发送 SIGHUP 信号(挂断并终止进程)。

Zsh 进阶特性

  • 省略 cd:直接输入目标目录名称即可进入。
  • 快速向上跳转:键入 n+1 个 . 可向上跳转 n 层目录(例如 ... 跳转两层)。
  • 进程名补全:输入 kill process_nameTab 键,可自动将进程名替换为对应 PID。
  • 目录访问栈:输入 d 列出最近访问过的目录列表,随后输入对应编号即可快速切换。
  • 路径首字母补全:如需进入 ~/workspace/src/dict,直接输入 cd ~/w/s/d 并按 Tab 即可自动补全完整路径。
  • 快速重试:输入 r 重新执行上一条命令。
  • 历史搜索过滤:先输入部分命令(如 git),再按 键即可在历史记录中检索所有以该前缀开头的命令。
  • 全局通配符 (Globbing):使用 ** 进行递归搜索,如 ls **/*.png 可列出当前及所有子目录下的 PNG 文件。

常用命令

文件与目录管理

命令功能说明常用选项
ls列出目录内容l='ls -lah':以人类可读格式详细列出所有文件(含隐藏文件)。
du查看磁盘使用情况-h:人类可读格式;-d 0:指定目录深度为 0(仅看当前层总和)。
mkdir创建目录-p:递归创建多级目录,建议设别名 md='mkdir -p'
cd切换工作目录-
rm删除文件或目录-rf:强制且递归删除(高危操作,需谨慎)。
cp复制文件或目录-r:递归复制目录;-p:连带文件属性复制;-a:相当于 -rpd (归档模式)。
mv移动或重命名文件/目录-

文件与命令检索

  • locate [文件名]:依赖后台数据库进行模糊搜索,速度极快(默认每天更新一次)。
    • 配合 updatedb 可强制手动更新数据库。
    • 配置文件位于 /etc/updatedb.conf,可设置搜索限制(如跳过特定系统路径或文件类型)。
  • find [搜索路径] [条件]:实时遍历文件系统,支持复杂逻辑的完全匹配搜索。
    • 按名称-name (精确大小写),-iname (忽略大小写)。
    • 按时间/大小/逻辑组合
      • find . -mtime +10:查找修改时间超过 10 天的文件。
      • find . -size -25k:查找小于 25 KB 的文件。
      • find . -size +50k -o -size -20k:查找大于 50 KB 或小于 20 KB 的文件(-o 表示 OR 逻辑)。
      • find . -size +20k -size -50k -exec ls -lh {} \;:查找 20 KB 到 50 KB 之间的文件,并对结果执行 ls -lh 打印详细信息。
  • whereis [命令名]:定位二进制可执行文件 (-b) 及帮助手册页 (-m) 的绝对路径。
  • which [命令名]:打印当前 PATH 环境下该命令的具体调用路径(可显示 alias 别名)。
  • grep [选项] 字符串 [文件名]:基于正则表达式的文本行过滤与包含匹配。
    • -i:忽略大小写。
    • -v:反向选择,输出不包含指定字符串的行。
    • -C [数字]:打印上下文 (Context),例如 grep -C 2 会同时输出匹配行的上下各两行内容。

进程与任务管理

  • kill [PID]:发送信号终止指定 PID 的进程。
  • pkill [进程名]:按进程名称模式批量终止进程(支持 Tab 补全)。
  • fg / bg:将后台挂起(暂停)的进程调至前台 (Foreground) 运行 / 让其在后台 (Background) 继续运行。
  • jobs:查看当前终端会话中未完成的所有后台任务。

系统与其他实用命令

  • man [命令]:查阅命令的官方帮助文档 (Manual)。
  • systemctl suspend:使系统进入休眠状态。
  • cat [file] | xclip -selection clipboard:将文件内容打印并复制到系统剪贴板(依赖 xclip)。
  • sips --resampleWidth [像素]:使用脚本进行图像缩放处理(macOS 专有命令)。

SSH

Unix 系统中的 SSH 架构包含客户端 openssh-client 与服务端 openssh-server。客户端通常为系统内置,用于向外发起连接。

服务端配置与状态检测

  • 开启 SSH Server
    • Ubuntu:执行 sudo apt-get install openssh-server 进行安装。
    • macOS:进入系统设置,开启「Sharing -> Remote Login」。
  • 状态检测:运行 ps -e | grep ssh。若输出包含 sshd,即表明服务端已启动并正在运行。
  • 配置文件:服务端主配置文件位于 /etc/ssh/sshd_config,默认监听 22 端口,可在此处修改端口及访问控制等设置。

连接与快捷访问

通过 ifconfig 获取本机 IP 地址后,其他客户端可通过 ssh username@ip 建立连接。

配置快捷别名:编辑或创建 ~/.ssh/config,添加以下配置模板。配置完成后,直接使用 ssh [自定义名称] 即可快速连接。

1
2
3
4
5
Host [自定义名称]
HostName [IP 地址]
User [服务端用户名]
Port [端口号]
IdentityFile [私钥绝对路径]

免密登录 (Public Key Authentication)

利用公钥加密机制实现免输入密码的安全验证。

1
2
3
4
# 生成 RSA 密钥对(公钥与私钥)
ssh-keygen -t ed25519 -C "your_email@example.com"
# 将公钥安全传输并追加至服务端的 authorized_keys 中
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip

网络连接注意事项

进行远程连接时,需特别注意网络拓扑与 IP 分配机制:

  • 内外网隔离:必须区分内网 IP 与公网 IP。连接在同一路由器下的设备处于相同局域网,路由器分配的内网 IP 仅限该局域网内通信。
  • 外网访问与端口转发:从外部网络连接本机,需使用路由器的公网 IP,并在路由器管理界面设置端口转发 (Port Forwarding),将外部端口映射至本机的 22 端口。
  • 运营商内网陷阱:需核实路由器 WAN 口获取的 IP 是否为真实的公网 IP。许多宽带用户实际处于运营商的级联大内网 (CGNAT) 中,此时传统的端口转发将失效。
  • 动态 IP 与 DDNS:若拥有真实公网 IP 但该 IP 会动态改变,需配置 DDNS (动态域名解析服务) 将域名实时绑定至变动的 IP 地址上。

:部分地区(如美国)的家用宽带公网 IP 变动频率极低,几乎可视作静态。

Vim

Vim Keyboard
Vim Keyboard

推荐新手在终端中运行 vimtutor 命令进行交互式基础学习。

操作模式

核心原则:同样的按键在不同模式下具备完全不同的功能。

模式名称核心功能快捷键切换
Normal移动光标、删除或复制文本(默认模式)。Esc
Insert插入与编辑文本。i
Replace覆盖替换现有文本。R
Visual高亮选择文本块。v
Command-line执行保存、退出、搜索等全局命令。:

启动参数

利用参数可在打开文件时直接定位或采用特定视图:

  • vim + [file]:打开文件并将光标定位到最后一行。
  • vim +3 [file]:打开文件并将光标定位到第 3 行。
  • vim +/xxx [file]:打开文件并定位到首个匹配 xxx 的行,可按 n 键跳转至下一个匹配项。
  • vim [file1] [file2]:在同一个窗口的后台缓冲区 (Buffer) 中打开多个文件。
    • 配合 :n (下一个文件)、:N:prev (上一个文件) 进行切换。
    • 输入 :b 后按 Tab 键可自动补全并切换文件。
  • vim -p [file1] [file2]:以标签页形式打开多个文件,使用 gt (下一个) 或 gT (上一个) 切换标签。

命令行模式常用命令

命令功能说明
:w / :q / :wq保存 / 退出 / 保存并退出。
:x保存(仅当文件有修改时)并退出。
:[command]!强制执行命令(如 :q! 放弃保存强制退出)。
:e [file]在当前窗口打开新文档。
:ls列出当前加载至缓冲区的所有文件。
:h [topic]打开内建帮助文档(可查询具体命令或按键)。
:w [name]另存为 [name]。若在 Visual 模式下选中部分内容,则仅另存选中部分。
:r [name]读取指定文件内容并插入至光标下一行。
:r ![cmd]执行 Shell 命令(如 !ls)并将其输出结果插入至光标下一行。

光标移动

  • 基础方向h (左) / j (下) / k (上) / l (右)。
  • 单词跳转w (跳至下个单词词首) / e (跳至单词词尾) / b (跳至本/上个单词词首)。
  • 行内跳转0 (绝对行首) / ^ (行首首个非空字符) / $ (绝对行尾)。
  • 屏幕视窗H (屏幕顶部) / M (屏幕中部) / L (屏幕底部)。
  • 翻页操作Ctrl + f / Ctrl + b (向下 / 上翻全页),Ctrl + d / Ctrl + u (向下 / 上翻半页)。
  • 文件首尾与定行gg (文件第一行) / G (文件最后一行)。跳转至指定行使用 :[行号][行号]G(如 :1515G)。
  • 行内字符查找f / F (向后 / 前查找字符,光标停留在字符上);t / T (向后 / 前查找,光标停在目标字符的前一个位置)。
  • 模式匹配搜索/[regex] 向下搜索,?[regex] 向上搜索。使用 n / N 跳转至下一个 / 上一个匹配项。
  • 括号匹配% 自动在配对的 ()[]{} 之间跳转。
  • 标记与历史m[X] 设定一个名为 X 的书签 (Mark),使用 `[X] 直接定位回该标记。Ctrl + o / Ctrl + i 用于在跳转历史中后退 / 前进。

注意:在 Visual 模式下同样使用移动键来扩展选取范围。

文本编辑

快捷键/命令功能说明
o / O在当前光标所在行的下方 / 上方开启新行并进入 Insert 模式。
> / >>增加缩进。>> 表示缩进当前整行。
d[motion]删除文本组合。例如 dw 删除一个单词,d$ 删除至行尾,d0 删除至行首,dd 删除整行。
c[motion]修改文本(等效于 d[motion] + i,即删除后进入 Insert 模式)。如 cw 修改单词。
x / sx 删除单个字符(等效于 dl);s 替换单个字符并进入插入模式(等效于 xi)。
r替换当前字符,但不进入 Insert 模式。
y[motion]复制文本。yy 复制整行,yw 复制单词。
p / P在光标之后 / 之前粘贴剪贴板 (Register) 内容。
u / U / Ctrl + r撤销上次操作 / 撤销整行所有修改 / 重做撤销的操作。
d / c在 Visual 模式选中内容后,按 d 删除,按 c 修改。

文本对象 (Text Objects):推荐在 d (删除) 或 c (修改) 操作中配合 Text Objects 使用,而非单纯的 Motion。

  • iw (inner word):单词内部。
  • it (inner tag):XML/HTML 标签内部。
  • i" (inner quotes):双引号内部。
  • ip (inner paragraph):段落内部。
  • as (a sentence):包含标点的整句。

全局替换 (Substitution)

  • :s/[a]/[b]:将光标所在行第一个匹配的 a 替换为 b
  • :s/[a]/[b]/g:替换光标所在行所有匹配项(g 代表 global)。
  • :[#],[#]s/[a]/[b]/g:在指定的起止行号内进行全部替换。
  • :%s/[a]/[b]/g:在整个文件范围内进行全部替换。
  • :%s/[a]/[b]/gc:全局替换,但在每次替换前请求确认(c 代表 confirm)。

特殊技巧与高级配置

  • 重复操作. (点操作符) 可重复执行上一次的修改指令。
  • 组合威力:搜索与编辑可完美结合。例如 dt" 会删除从当前光标一直到该行首个 " 符号之前的所有内容。
  • 数字修饰符[数字] + [命令] 可重复执行多次。如 3w 代表向前移动 3 个单词。
  • 寄存器 (Registers):使用 dx 删除的文本并不会凭空消失,而是自动放入了默认寄存器中,随后可用 p 粘贴。
  • 当前状态Ctrl + g 显示当前文件的路径信息及光标所处状态。
  • 命令行补全:在 Command-line 模式下,按 Ctrl + d 会列出所有可能的自动补全选项。
  • 开关设置:在命令前加 no 可快速关闭该选项。例如 :set noic (关闭 ignore-case,即开启大小写敏感搜索)。
  • 重载配置:so % 表示将当前文件作为 VimScript 配置加载。:so ~/.vimrc 则是重新加载用户指定的 Vim 配置文件。

Tmux

Tmux 是一个强大的终端复用器,其层级结构严格遵循:会话 (Session) -> 窗口 (Window) -> 窗格 (Pane)

核心概念:Tmux 中的大部分快捷键操作都需要先按下前缀键 (Prefix) 激活指令模式,默认的前缀键组合为 Ctrl + b

会话管理 (Session)

每个会话都是一个独立的工作空间。其最大优势在于:即使断开终端或 SSH 连接,会话及其内部的进程也会在后台稳定运行。

命令 / 快捷键功能说明
tmux开启一个未命名的新会话。
tmux new -s [NAME]开启新会话并自定义命名。
tmux new -A尝试接入上一个会话;若当前不存在任何会话,则新建一个。
tmux ls列出当前所有在后台运行的会话。
tmux a接入 (attach) 最后一个活动的会话。
tmux a -t [name]接入特定名称的目标会话。
Ctrl + b 后按 d分离 (detach) 当前会话。退出 Tmux 界面,但保持会话在后台继续运行。

窗口管理 (Window)

窗口类似于现代浏览器的标签页,多个窗口可以同属于一个会话。

快捷键(需先按 Prefix)功能说明
c创建新窗口 (create)。
[N]跳转至编号为 N 的窗口。
p / n切换至上一个 / 下一个窗口。
,重命名当前活动窗口。
w以可视化列表形式展示当前所有窗口,支持上下选择跳转。
Ctrl + d关闭当前窗口。(本质是向 Shell 传递 EOF 终止进程)

窗格管理 (Pane)

窗格是对当前单一窗口的屏幕区域进行任意分割的结果。

快捷键 (需先按 Prefix)功能说明
"水平划分窗格(即上下分割)。
%垂直划分窗格(即左右分割)。
[方向键]将光标焦点切换至对应方向的相邻窗格。
z全屏放大当前窗格 / 再次按下则取消全屏恢复原状 (zoom)。
<Space>空格键,在 Tmux 预设的几种窗格排列布局之间循环切换。

Git

关于 Git 的核心概念与常用操作,参见另一篇笔记:Git 101

Debugging & Profiling

Debugging (代码调试)

推荐使用 ipdb 进行 Python 代码调试。它是基于 IPython 的增强版 pdb,原生支持语法高亮、自动补全等进阶功能。启动方式:

1
python -m ipdb [脚本文件.py]

常用交互命令 (Interactive Commands)

命令缩写(全拼)功能说明
l (list)打印当前执行行及其上下共 11 行代码(支持重复输入以向下翻阅代码)。
s (step)单步执行当前行(若遇到函数调用,会步入函数内部)。
n (next)单步执行当前行(若遇到函数调用,会跳过该函数,直接去往下一行)。
c (continue)持续运行代码,直到触发下一个断点或程序异常抛错。
b (break)设定断点(可指定行号或函数名)。
p (print)计算并打印当前上下文作用域中的变量值。
r (return)继续执行代码,直到当前所在的函数遇到 return 返回。
q (quit)强制终止调试进程并退出。

Profiling (性能分析)

执行耗时测算time 命令,用于粗略评估终端命令的运行耗时。

  • real: Elapsed real time,即从命令敲击回车到执行结束,现实世界实际流逝的总时间。
  • user: User CPU time,进程在用户空间中实际消耗的 CPU 时间总和。
  • sys: System CPU time,进程在内核空间中(如进行系统调用)消耗的 CPU 时间总和。

Python 细粒度性能分析工具

  • 时间开销追踪:使用 line_profiler 模块,可精确统计函数内每一行代码的执行耗时。
  • 内存占用追踪:使用 memory_profiler 模块,用于逐行监控脚本运行期间的内存分配与峰值情况。

Make

Make 是经典的自动化构建系统,适用于任何「基于文件变更状态触发重新构建」的项目。

其核心原理是根据 Makefile 中编写的规则,执行指定的 Shell 命令序列。

Makefile 基础

Makefile 的基础语法结构如下:

1
2
[target]: [dependency1] [dependency2] ...
    [command]

高危易错点[command] 所在的行首必须使用 Tab 键缩进,严禁使用空格代替。

  • Dependency Graph: dependency (依赖项) 可以拥有自身的构建规则,Make 会自动解析并形成完整的依赖调用链。
  • Phony Target: target (目标) 既可以是具体生成的文件,也可以是单纯的执行动作(如 clean)。为防止这些动作名与当前目录下的同名文件发生冲突,需在开头使用 .PHONY 显式声明它们。

综合范例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.PHONY clean all

all: hello.out  # 定义的默认/伪目标

hello.out: hello.c min.o max.o
    gcc -o hello.out hello.c min.o max.o

# 若执行时发现缺少 .o 文件,Make 会向下检索对应的依赖规则并递归执行
min.o: min.c
    gcc -c -o min.o min.c

max.o: max.c
    gcc -c -o max.o max.c

clean:  # 清理编译产物(伪目标)
    rm *.out *.o

核心语法与高级特性

变量与输出控制

  • 定义与调用变量:使用等号赋值,通过 $() 调用。
  • 关闭回显make 默认会打印每条正在执行的命令。在命令前加上 @ 符号可抑制该输出。
1
2
3
txt=HELLO
test:
    @echo $(txt)  # 只打印 HELLO,不打印 echo HELLO 这条命令本身

自动变量 (Automatic Variables)

用于在规则命令中动态指代目标或依赖:

  • $@: 代表当前的 target 名称。
  • $^: 代表所有的 dependency 集合(以空格分隔)。
  • $<: 代表第一个 dependency 的名称。
1
2
a.txt: b.txt c.txt
    echo $^ > $@  # 将 b.txt c.txt 写入 a.txt

模式匹配与内置函数

  • 模式匹配:使用 % 符号进行通配,可大幅简化结构高度一致的规则。
  • 内置函数:提供文本和文件处理能力。
    • wildcard: 提取匹配的真实文件列表。
    • patsubst: 模式匹配替换,语法为 $(patsubst pattern,replacement,text)
1
2
3
4
5
6
7
8
# 1. 模式匹配示例
%.csv: %.txt  # 匹配所有 .csv 并将对应的 .txt 作为依赖
    echo $^ > $@

# 2. 内置函数示例
files = $(wildcard src/*.txt)  # 获取 src 目录下所有 txt 文件
# 将 a.txt b.txt 替换为 a.csv b.csv (注意 text 参数是以空格分隔的)
csv_files = $(patsubst %.txt,%.csv,a.txt b.txt)

Make 命令行参数

运行 make 时,系统默认在当前目录下寻找名为 Makefilemakefile 的文件。运行逻辑:仅当 target 不存在,或 dependency 的修改时间 (Timestamp) 比 target 更晚时,才会触发 command 执行。

命令 / 参数功能说明
make [target]执行指定的目标;若未指定,则默认执行 Makefile 中定义的第一个目标。
make -n [target]Dry-run (试运行):仅打印将要执行的命令,而不真正执行。
make -B [target]强制构建:无视文件新旧时间戳,无条件重新构建目标。
make -C [dir]切换目录:在执行前先切换到指定的目录 [dir]
make -f [file]指定文件:指定非默认名称的文件作为 Makefile 运行。

C++

GCC (GNU Compiler Collection)

GCC 编译 C/C++ 源码通常经历四个严格的阶段:预处理 -> 编译 -> 汇编 -> 链接

  • 预处理 (Preprocessing):编译器将被包含的头文件(如 #include)及宏定义展开并插入源码中。gcc -E hello.c -o hello.i
  • 编译 (Compilation):检查代码规范与语法错误。确认无误后,将预处理后的代码翻译为汇编语言。gcc -S hello.i -o hello.s
  • 汇编 (Assembly):将汇编代码 .s 文件转换为机器可读的二进制目标文件 (Object File)。
  • 链接 (Linking):将目标文件与所需的库文件链接,最终生成可执行文件。

常用编译参数

参数功能说明
-E仅执行预处理操作,不进行编译。
-S将 C 代码编译为汇编代码,不进行汇编与链接。
-c仅执行编译与汇编操作,生成 .o 目标文件,不进行链接
-o [file]指定生成的输出文件名。
-Wall开启所有常见的编译警告信息 (Warning All)。

CMake 构建系统

CMake 是基于 Makefile 的高层抽象工具,旨在跨平台自动生成可移植的 Makefile。其核心配置均写在 CMakeLists.txt 中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.19)

# 定义工程名称
project(Test)

# 设置编译模式 (Debug 或 Release)
set(CMAKE_BUILD_TYPE "Debug")

# 1. 编译可执行程序:将 a.cpp 编译为可执行文件 a (需包含 main 函数)
add_executable(a a.cpp)

# 2. 编译库文件:将 b.cpp 编译为静态库 (默认) 或共享/动态库 (SHARED)
add_library(b b.cpp)
add_library(b_ SHARED b.cpp)

# 3. 链接目标文件:c.cpp 中调用了库 b 的函数,需将其链接
add_executable(c c.cpp)
target_link_libraries(c b)

注意:在 c.cpp 中调用 b 库的函数时,需另外定义一个 b.h 头文件用于声明这些函数,并在 c.cpp 中通过 #include "b.h" 引入。

编译、安装与卸载流程

标准构建流程:建议采用外部构建 (Out-of-source build),即创建独立的 build 目录,以实现源码与生成产物的物理隔离。

1
2
3
4
5
cd <project>
mkdir build && cd build
cmake ..      # 读取上一层目录的 CMakeLists.txt 并生成 Makefile
make          # 执行编译
make install  # 执行安装 (需 CMakeLists.txt 中已配置 install 指令)

安装路径控制:第三方库的 install 指令通常会将头文件、库文件及可执行文件,分别放置到系统变量 CMAKE_INSTALL_PREFIX(默认为 /usr/local)下的 include/lib/bin/ 目录中。

  • 可通过参数改变安装路径:cmake -DCMAKE_INSTALL_PREFIX=<自定义路径> ..

安全卸载:执行 make uninstall 卸载。若项目未提供 uninstall 规则,可前往原编译 build 目录中寻找 install_manifest.txt(记录了所有安装文件的绝对路径)。

  • 手动卸载命令:xargs rm < install_manifest.txt

依赖管理 (find_package)

用于在 CMake 中导入第三方库。基础语法:

1
find_package(<PackageName> REQUIRED)

搜索机制:CMake 会依据一定的优先级寻找名为 <PackageName>Config.cmake 等配置清单。核心搜索路径包括

  1. <PackageName>_DIR 变量
  2. CMAKE_PREFIX_PATH 变量
  3. 系统环境 PATH

CMake Package Registry: 若未执行 make install,但 find_package 依然能成功找到库,通常是因为 CMakeLists.txt 中使用了 export 指令。这会将构建路径注册到用户级注册表 ~/.cmake/package/<PackageName> 中。

调用变量:成功执行 find_package 后,CMake 会自动抛出该库的相关变量供后续链接使用,最常见的两个为

  • <PackageName>_INCLUDE_DIRS (头文件路径)
  • <PackageName>_LIBS (库文件名称)

Q & A

脚本执行方式对比 (source vs exec vs ./script)

  • source: 在当前 Shell 环境中读取并执行指令(不创建子进程)。
  • exec: 用新的进程替换当前 Shell 进程执行命令(执行完毕后,原 Shell 进程也会随之终止)。
  • ./script: 派生 (Fork) 出一个新的子 Shell 环境,在其中执行命令;执行完毕后子 Shell 退出,返回父 Shell。

最佳实践:重新加载 .zshrc 配置时,强烈建议使用 exec zsh(直接替换当前进程以刷新环境),而非 source ~/.zshrc(可能导致环境变量无休止地累加或污染)。

macOS 与 Linux 核心命令链差异

Linux 默认使用 GNU 版本的核心工具集,而 macOS 默认使用 BSD 版本,两者的命令参数与行为存在差异。

  • 解决方案:在 macOS 上可通过 Homebrew 安装 GNU 工具集:brew install coreutils
  • 使用方式:安装后的命令默认位于 /usr/local/bin,且带有 g 前缀(如 gls 代替 lsgdate 代替 date)。
  • 全局替换:若希望完全替代 macOS 自带命令,可在 /usr/local/bin 中为这些命令建立去掉 g 前缀的软链接。因为在系统默认的 PATH 环境变量中,/usr/local/bin 的优先级高于系统原生的 /usr/bin

文件与目录命名规范

  • 绝对禁忌永远不要在文件或目录名称中使用空格。在命令行(特别是 Shell 脚本批处理)中,空格会被默认识别为参数分隔符,这会带来无尽的转义麻烦。
  • 补救措施:若因历史遗留等客观原因无法避免带空格的命名,且仅涉及极少数文件或文件夹,建议在同级目录下为它们创建命名规范(如使用下划线 _ 或连字符 -)的软链接。

Trivia (冷知识)

  • rc 后缀的含义:各类终端及软件配置文件(如 .bashrc, .zshrc, .vimrc)后缀中的 rc,其全称为 Run Commands
  • bash 的双关语谐音梗:早期的 Unix 主力 Shell 叫做 Bourne Shell(由 Stephen Bourne 开发,简称 sh)。后来 GNU 计划开发了一款强大的替代品,幽默地将其命名为 Bourne Again Shell,缩写即为 bash。这恰好与英文的 “born again” 完美同音。
  • grep 名字的由来:它来源于早期 Unix 文本编辑器 ed 中的一条极其高频的操作指令 g/re/p。意思是 Global Regular Expression Print。
  • Vim 方向键的历史遗留:其前身 vi 诞生时,作者 Bill Joy 使用的终端机上并没有独立的方向键,上下左右的箭头恰好印在 H J K L 这四个按键上;同时,Home 键和 ~ 波浪号也被整合在了同一个按键上。