The Missing Semester of Your CS Education - Notes
Lecture 1: The Shell
什么是Shell
Shell是一种命令语言,也是一种程序设计语言。作为命令语言,当用户输入一个指令,Shell能马上提供反馈结果,与用户进行实时交互;作为程序设计语言,支持定义各种变量参数,提供循环、分支、函数编程、脚本编写的功能。Shell是操作系统最外的一层,是文字操作系统与外部最主要的接口,管理用户和操作系统之间的交互 Shell主要有两大类:
- 图形Shell(Graphical User Interface Shell, GUI Shell) 例如此电脑中的文件管理系统
- 命令行Shell(Command Line Interface Shell, CLI Shell) 包括bash/ sh/ ksh/ csh/ zsh, Windows中的cmd.exe/ PowerShell
我们主要使用的是Bourne Again SHell,简称 bash,由于没有mac,我使用的是在Windows PowerShell 中打开WSL中Linux系统下的Shell,如:
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant#root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant## 说明我们是 root 用户
Date 作为内置程序输出日期
root# date
Wed Jan 21 12:58:34 CST 2026root# date
Wed Jan 21 12:58:34 CST 2026Echo 的作用是
Echo the STRING(s) to standard output.
root# echo hello
helloroot# echo hello
hello当我们在 Shell 中执行命令时,如果改指令不是 shell 所了解的编程关键字,就会咨询环境变量 $PATH
root# which echo
/usr/bin/echo
root# /usr/bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binroot# which echo
/usr/bin/echo
root# /usr/bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin目录导航:pwd 与 cd
pwd 代表当前目录地址,切换目录使用 cd 命令,Linux 中 / 代表系统根目录,. 代表当前目录,.. 代表上级目录,表示上上级可用 ../..
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# pwd
/mnt/c/Users/Panchant
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# cd home
-bash: cd: home: No such file or directory
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# cd /home
root@DESKTOP-Q64GDMO:/home# pwd
/home
root@DESKTOP-Q64GDMO:/home# mkdir missing
root@DESKTOP-Q64GDMO:/home# cd missing/
root@DESKTOP-Q64GDMO:/home/missing# pwd
/home/missing
root@DESKTOP-Q64GDMO:/home/missing# ../../bin/echo hello
hello
root@DESKTOP-Q64GDMO:/home/missing# cd ..
root@DESKTOP-Q64GDMO:/home#root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# pwd
/mnt/c/Users/Panchant
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# cd home
-bash: cd: home: No such file or directory
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# cd /home
root@DESKTOP-Q64GDMO:/home# pwd
/home
root@DESKTOP-Q64GDMO:/home# mkdir missing
root@DESKTOP-Q64GDMO:/home# cd missing/
root@DESKTOP-Q64GDMO:/home/missing# pwd
/home/missing
root@DESKTOP-Q64GDMO:/home/missing# ../../bin/echo hello
hello
root@DESKTOP-Q64GDMO:/home/missing# cd ..
root@DESKTOP-Q64GDMO:/home#查看目录:ls 命令
使用 ls 查看目录下的文件:
root@DESKTOP-Q64GDMO:/# ls
bin dev home lib lib64 lost+found mnt proc run snap sys usr wslEHEmph wslPCeknh wslpnAkAi
boot etc init lib32 libx32 media opt root sbin srv tmp var wslMJNFOg wsldONNAi
root@DESKTOP-Q64GDMO:/# ls /home
missing panchant
root@DESKTOP-Q64GDMO:/# ls -l /home
total 8
drwxr-xr-x 2 root root 4096 Jan 21 13:19 missingroot@DESKTOP-Q64GDMO:/# ls
bin dev home lib lib64 lost+found mnt proc run snap sys usr wslEHEmph wslPCeknh wslpnAkAi
boot etc init lib32 libx32 media opt root sbin srv tmp var wslMJNFOg wsldONNAi
root@DESKTOP-Q64GDMO:/# ls /home
missing panchant
root@DESKTOP-Q64GDMO:/# ls -l /home
total 8
drwxr-xr-x 2 root root 4096 Jan 21 13:19 missing权限管理:chmod 命令
chmod(change mode)命令是 Linux/Unix 系统中用于修改文件或目录访问权限的核心工具。
在 Linux 中,权限被划分为三个层级: Owner (u):文件所有者; Group (g):文件所属的用户组; Others (o):其他所有用户;All (a):以上所有类别。
运行 ls -l 时,会看到类似 -rwxr-xr-- 的字符串,分别代表不同含义:
- 第 1 位:文件类型(
-为文件,d为目录)。 - 第 2-4 位:所有者权限(rwx)。
- 第 5-7 位:所属组权限(r-x)。
- 第 8-10 位:其他用户权限(r—) 我们通常使用三个八进制数字法来代表权限,每个数字是 读 (4)、写 (2)、执行 (1) 的累加值。
| 数字 | 权限组合 | 含义 |
|---|---|---|
| 7 | 4+2+1 | 读 + 写 + 执行 (rwx) |
| 6 | 4+2 | 读 + 写 (rw-) |
| 5 | 4+1 | 读 + 执行 (r-x) |
| 4 | 4 | 只读 (r—) |
| 0 | 0 | 无任何权限 (---) |
chmod 777 file:所有人都有所有权限(不安全,慎用)。chmod 755 file:所有者全开,组和其他人可读可执行(脚本/程序的常用权限)。chmod 644 file:所有者可读写,组和其他人只读(普通文档的常用权限)。
root@DESKTOP-Q64GDMO:/home/missing# touch semester
root@DESKTOP-Q64GDMO:/home/missing# echo '#!/bin/sh' > semester
root@DESKTOP-Q64GDMO:/home/missing# echo curl --head --silent https://missing.csail.mit.edu >> semester
root@DESKTOP-Q64GDMO:/home/missing# cat semester
#!/bin/sh
curl --head --silent https://missing.csail.mit.edu
root@DESKTOP-Q64GDMO:/home/missing# ./semester
-bash: ./semester: Permission denied
root@DESKTOP-Q64GDMO:/home/missing# ls -l
total 16
-rw-r--r-- 1 root root 6 Jan 21 14:43 hello.txt
-rw-r--r-- 1 root root 2 Jan 21 14:48 hello2.txt
-rw-r--r-- 1 root root 61 Jan 21 14:58 semester
-rw-r--r-- 1 root root 28 Jan 21 14:55 test.txt
root@DESKTOP-Q64GDMO:/home/missing# chmod 777 semester
root@DESKTOP-Q64GDMO:/home/missing# ls -l
total 16
-rw-r--r-- 1 root root 6 Jan 21 14:43 hello.txt
-rw-r--r-- 1 root root 2 Jan 21 14:48 hello2.txt
-rwxrwxrwx 1 root root 61 Jan 21 14:58 semester
-rw-r--r-- 1 root root 28 Jan 21 14:55 test.txt
root@DESKTOP-Q64GDMO:/home/missing# ./semesterroot@DESKTOP-Q64GDMO:/home/missing# touch semester
root@DESKTOP-Q64GDMO:/home/missing# echo '#!/bin/sh' > semester
root@DESKTOP-Q64GDMO:/home/missing# echo curl --head --silent https://missing.csail.mit.edu >> semester
root@DESKTOP-Q64GDMO:/home/missing# cat semester
#!/bin/sh
curl --head --silent https://missing.csail.mit.edu
root@DESKTOP-Q64GDMO:/home/missing# ./semester
-bash: ./semester: Permission denied
root@DESKTOP-Q64GDMO:/home/missing# ls -l
total 16
-rw-r--r-- 1 root root 6 Jan 21 14:43 hello.txt
-rw-r--r-- 1 root root 2 Jan 21 14:48 hello2.txt
-rw-r--r-- 1 root root 61 Jan 21 14:58 semester
-rw-r--r-- 1 root root 28 Jan 21 14:55 test.txt
root@DESKTOP-Q64GDMO:/home/missing# chmod 777 semester
root@DESKTOP-Q64GDMO:/home/missing# ls -l
total 16
-rw-r--r-- 1 root root 6 Jan 21 14:43 hello.txt
-rw-r--r-- 1 root root 2 Jan 21 14:48 hello2.txt
-rwxrwxrwx 1 root root 61 Jan 21 14:58 semester
-rw-r--r-- 1 root root 28 Jan 21 14:55 test.txt
root@DESKTOP-Q64GDMO:/home/missing# ./semester使用 man 来展示某个程序的用户手册
root@DESKTOP-Q64GDMO:/# man lsroot@DESKTOP-Q64GDMO:/# man ls最后使用 q 退出
LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default). Sort entries alphabetically if none of
-cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all
do not ignore entries starting with .
-A, --almost-all
do not list implied . and ..
--author
with -l, print the author of each file
-b, --escape
print C-style escapes for nongraphic characters
--block-size=SIZE
with -l, scale sizes by SIZE when printing them; e.g., '--block-size=M'; see SIZE format below
Manual page ls(1) line 1 (press h for help or q to quit)LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default). Sort entries alphabetically if none of
-cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all
do not ignore entries starting with .
-A, --almost-all
do not list implied . and ..
--author
with -l, print the author of each file
-b, --escape
print C-style escapes for nongraphic characters
--block-size=SIZE
with -l, scale sizes by SIZE when printing them; e.g., '--block-size=M'; see SIZE format below
Manual page ls(1) line 1 (press h for help or q to quit)流的使用
< 是将文件的内容作为输入,> 是将终端的信息作为输入
root@DESKTOP-Q64GDMO:/home/missing# echo hello > hello.txt
root@DESKTOP-Q64GDMO:/home/missing# cat hello.txt
hello
root@DESKTOP-Q64GDMO:/home/missing# cat < hello.txt
hello
root@DESKTOP-Q64GDMO:/home/missing# cat < hello.txt > hello2.txt
root@DESKTOP-Q64GDMO:/home/missing# cat hello2.txt
hello
root@DESKTOP-Q64GDMO:/home/missing#root@DESKTOP-Q64GDMO:/home/missing# echo hello > hello.txt
root@DESKTOP-Q64GDMO:/home/missing# cat hello.txt
hello
root@DESKTOP-Q64GDMO:/home/missing# cat < hello.txt
hello
root@DESKTOP-Q64GDMO:/home/missing# cat < hello.txt > hello2.txt
root@DESKTOP-Q64GDMO:/home/missing# cat hello2.txt
hello
root@DESKTOP-Q64GDMO:/home/missing#注意: > 是覆盖重定向 (Override), 而 >> 是追加重定向 (Append) ,如
root@DESKTOP-Q64GDMO:/home/missing# touch test.txt
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is >' > test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is >
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is override' > test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is override
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is append' >> test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is override
it is appendroot@DESKTOP-Q64GDMO:/home/missing# touch test.txt
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is >' > test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is >
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is override' > test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is override
root@DESKTOP-Q64GDMO:/home/missing# echo 'it is append' >> test.txt
root@DESKTOP-Q64GDMO:/home/missing# cat test.txt
it is override
it is append管道
| 操作符将一个程序的输出和另一个程序的输入连接在一起
root@DESKTOP-Q64GDMO:/home/missing# echo 3 | tee hello2.txt
3
root@DESKTOP-Q64GDMO:/home/missing# cat hello2.txt
3
root@DESKTOP-Q64GDMO:/home/missing# cat hello.txt
helloroot@DESKTOP-Q64GDMO:/home/missing# echo 3 | tee hello2.txt
3
root@DESKTOP-Q64GDMO:/home/missing# cat hello2.txt
3
root@DESKTOP-Q64GDMO:/home/missing# cat hello.txt
helloLecture 2: Shell Tools and Scripting
Shell Script 是一系列 Shell 命令的集合,保存在一个文本文件中,按照顺序依次执行。
Shell 变量
变量赋值
在 Shell 中给变量赋值,最核心的规则是:等号 = 两边绝对不能有空格。
错误写法:foo = bar(Shell 会把 foo 当成命令,= 和 bar 当成参数)
name="Mike"
age=25name="Mike"
age=25访问变量
赋值后,使用美元符号 $ 来提取变量的值。为了避免歧义,推荐使用 ${} 包裹变量名。
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $name
Mike
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "I am ${age} years old"
I am 25 years oldroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $name
Mike
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "I am ${age} years old"
I am 25 years old引号区别
在赋值或使用变量时,单引号和双引号的行为完全不同:
- 双引号 (
"):允许变量替换和转义字符。 - 单引号 (
'):完全字面量,引号内的任何字符都会原样输出,不进行变量解析。
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# greating="Helloworld"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "$greeting"
Helloworld
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo '$greeting'
$greetingroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# greating="Helloworld"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "$greeting"
Helloworld
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo '$greeting'
$greeting命令替换
如果你想把一个命令的输出结果赋值给变量,可以使用 $(command)
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# current_path=$(pwd)
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "$current_path"
/mnt/c/Users/Panchantroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# current_path=$(pwd)
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo "$current_path"
/mnt/c/Users/Panchant环境变量与 export
普通赋值定义的变量是局部变量,只在当前进程中有效。如果你希望子进程(比如你运行的一个脚本)也能访问这个变量,需要使用 export
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# MY_VAR="secret"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# export MY_VARroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# MY_VAR="secret"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# export MY_VARMY_NAME="Alice"
echo $MY_NAME # 输出 Alice
bash # 开启一个新的子 Shell
echo $MY_NAME # 输出为空,因为子进程拿不到父进程的局部变量
exit # 退回到原来的 Shell
export MY_AGE=20
echo $MY_AGE # 输出 20
bash # 开启一个新的子 Shell
echo $MY_AGE # 输出 20,环境变量被成功传给了子进程
exitMY_NAME="Alice"
echo $MY_NAME # 输出 Alice
bash # 开启一个新的子 Shell
echo $MY_NAME # 输出为空,因为子进程拿不到父进程的局部变量
exit # 退回到原来的 Shell
export MY_AGE=20
echo $MY_AGE # 输出 20
bash # 开启一个新的子 Shell
echo $MY_AGE # 输出 20,环境变量被成功传给了子进程
exit特殊变量
| 变量 | 含义 |
|---|---|
$0 | 脚本本身的名称 |
$1 - $9 | 传递给脚本的第 1 到第 9 个参数 |
$# | 传递给脚本的参数个数 |
$? | 上一条命令的退出状态码(0 表示成功) |
$$ | 当前进程的 PID |
| 下面这就是一个创建文件夹并进入的脚本 |
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# mcd(){
> mkdir -p "$1"
> cd "$1"
> }root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# mcd(){
> mkdir -p "$1"
> cd "$1"
> }返回码
返回码(Return Code)也称为退出状态码(Exit Status)。它是每个命令执行完毕后返回给操作系统的一个整数(范围通常是 0-255)。与编程语言中常见的 true=1, false=0 不同,Shell 的设计逻辑是:
0:表示成功(Success / OK)。- 非
0(1-255):表示失败或出现了某种异常情况。
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# ls /homw
ls: cannot access '/homw': No such file or directory
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $?
2
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# ls /home
missing panchant
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $?
0root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# ls /homw
ls: cannot access '/homw': No such file or directory
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $?
2
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# ls /home
missing panchant
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# echo $?
0使用退出码进行“短路运算”:
在 Shell 中,经常会看到 && 和 ||,它们本质上是根据上一条命令的退出码来决定是否执行下一条:
&&(与):当前面的命令返回 0 时,才执行后面的命令。mkdir test && cd test(如果创建目录成功,就进入该目录)
||(或):当前面的命令返回 非 0 时,才执行后面的命令。ls file.txt || echo "File not found"(如果找不到文件,就打印报错)
- 同一行的多个命令可以用
;分隔
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false || echo "Oops, fail"
Oops, fail
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# true || echo "Will not be printed"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# true && echo "Things went well"
Things went well
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false && echo "Will not be printed"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false; echo "This will always run"
This will always runroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false || echo "Oops, fail"
Oops, fail
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# true || echo "Will not be printed"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# true && echo "Things went well"
Things went well
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false && echo "Will not be printed"
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# false; echo "This will always run"
This will always run通配符
通配符(Wildcards),也叫 Globbing,是系统用来批量匹配文件或目录名的特殊字符。 核心通配符:
| 通配符 | 含义 | 例子 | 匹配结果示例 |
|---|---|---|---|
* | 匹配任意数量字符(包括 0 个) | *.txt | a.txt, script.txt, .txt |
? | 匹配一个任意字符 | file?.log | file1.log, fileA.log (不匹配 file10.log) |
[ ] | 匹配括号内的任一字符 | [abc].sh | a.sh, b.sh, c.sh |
[!] | 匹配不在括号内的任一字符 | [!a].sh | 匹配 b.sh,但不匹配 a.sh |
{ } | 花括号展开(匹配逗号分隔的任一模式) | *{.py,.sh} | 所有以 .py 或 .sh 结尾的文件 |
*是最常用的通配符。 |
ls *.jpg:列出所有 JPG 图片。rm temp_*:删除所有以temp_开头的文件。ls /usr/bin/z*:列出/usr/bin下所有以z开头的命令。?是精确的占位符,如果知道文件名的长度,?非常好用。ls image_??.png:匹配image_01.png,但不匹配image_1.png或image_100.png。[ ]是字符集合与范围[0-9]:匹配任何数字。[a-z]:匹配任何小写字母。[A-Za-z]:匹配任何字母。ls [BC]at.txt:匹配Bat.txt或Cat.txt。 花括号展开{ },虽然常和通配符一起用,但它的原理是生成字符串,而不仅仅是匹配已有的文件。- 批量创建文件:
touch file_{1..5}.txt会创建file_1.txt到file_5.txt。 - 批量备份:
cp config.php{,.bak}相当于执行cp config.php config.php.bak。
Shebang(Hashbang)
指的是出现在文本文件第一行前两个字符的 #!。在类 Unix 系统(Linux, macOS)中,它的作用是告诉系统使用哪个解释器(Interpreter)来执行这个脚本。
当你给一个脚本加上执行权限(chmod +x script.sh)并运行它(./script.sh)时
- 系统内核(Kernel)打开文件。
- 内核读取文件的前两个字节。
- 如果发现是
#!,内核会读取该行剩下的部分(例如/bin/bash)。 - 内核启动指定的解释器,并将你的脚本路径作为参数传递给它。
举个例子: 如果你的文件
hello.py第一行是#!/usr/bin/python3,当你运行./hello.py时,系统实际上执行的是:
/usr/bin/python3 ./hello.py/usr/bin/python3 ./hello.pyShell 工具
查找文件
1. find:实时搜索
find 会直接遍历硬盘上的目录树,功能极其强大,但如果目录文件太多,速度会稍慢。
基本语法:
find <搜索路径> <搜索条件> <操作>find <搜索路径> <搜索条件> <操作>常用场景:
- 按文件名查找 (
-name)bash# 在当前目录(.)及其子目录中查找名为 config.py 的文件 find . -name "config.py" # 使用通配符(注意:通配符建议加引号,防止被 Shell 提前展开) find /home -name "*.jpg" # 不区分大小写查找 (-iname) find . -iname "ReaDMe.txt"# 在当前目录(.)及其子目录中查找名为 config.py 的文件 find . -name "config.py" # 使用通配符(注意:通配符建议加引号,防止被 Shell 提前展开) find /home -name "*.jpg" # 不区分大小写查找 (-iname) find . -iname "ReaDMe.txt" - 按类型查找 (
-type)bash# 只找目录 (directory) find . -type d -name "src" # 只找普通文件 (file) find . -type f -name "run.sh"# 只找目录 (directory) find . -type d -name "src" # 只找普通文件 (file) find . -type f -name "run.sh" - 按时间查找
-mtime(Modification time):文件内容修改时间。
bash# 查找最近 24 小时内修改过的文件 find . -mtime -1 # 查找 7 天前修改过的文件 find . -mtime +7# 查找最近 24 小时内修改过的文件 find . -mtime -1 # 查找 7 天前修改过的文件 find . -mtime +7 - 按大小查找 (
-size)bash# 查找大于 100MB 的文件 find / -size +100M# 查找大于 100MB 的文件 find / -size +100M
2. locate:索引搜索
locate 不会真的去扫描硬盘,而是去查一个系统自带的数据库(通常位于 /var/lib/mlocate/)。
- 优点: 瞬间出结果,速度极快。
- 缺点: 非实时。如果你刚创建一个文件,
locate是找不到的,因为数据库还没更新。 现在 Ubuntu 一般为了保持轻量化,都没有安装locate,可以通过以下指令安装:
sudo apt install mlocatesudo apt install mlocate使用方法:
locate semesterlocate semester解决方案: 如果你找不到刚才创建的文件,可以强制更新数据库(通常需要 sudo):
sudo updatedbsudo updatedb代码查找
1. grep
grep (Global Regular Expression Print) 是所有 Linux 系统预装的工具。
基本用法
grep "要找的内容" <文件>grep "要找的内容" <文件>在项目中查找代码
通常我们需要在当前目录及其所有子目录中查找,并且显示行号。
# -r: 递归查找 (Recursive),遍历子目录
# -n: 显示行号 (Line number)
# .: 当前目录
grep -rn "main" .# -r: 递归查找 (Recursive),遍历子目录
# -n: 显示行号 (Line number)
# .: 当前目录
grep -rn "main" .参数详解
-i(Ignore case):忽略大小写(找Error时也能把error找出来)。-v(Invert):反向查找,显示不包含该内容的行。--color:高亮显示匹配到的文字(现在的 Linux 通常默认开启)。-C 3(Context):显示匹配行前后各 3 行的内容(方便看代码上下文)。
示例: 查找 semester 文件里包含 “curl” 的行,并忽略大小写:
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# grep -i "curl" /home/missing/semester
curl --head --silent https://missing.csail.mit.eduroot@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# grep -i "curl" /home/missing/semester
curl --head --silent https://missing.csail.mit.edu2. ripgrep (rg)
grep 其实不太好用,因为它会去搜索 .git 文件夹、编译生成的二进制文件或者巨大的 node_modules 文件夹,导致速度慢且输出乱。
而**ripgrep (rg)** 是专门为代码搜索设计的工具:
- 极快:比
grep快得多。 - 智能:自动忽略
.gitignore里列出的文件(比如node_modules)。 - 好看:输出结果自带文件名高亮和行号。
安装方法 (Ubuntu/WSL)
sudo apt install ripgrepsudo apt install ripgrep使用方法
非常简单,甚至不需要输 -r,它默认就是递归的:
# 在当前目录下找 "TODO"
rg "TODO"
# 在特定类型的代码中找(比如只在 Python 文件中找)
rg "import" -t py# 在当前目录下找 "TODO"
rg "TODO"
# 在特定类型的代码中找(比如只在 Python 文件中找)
rg "import" -t py查找 Shell 指令
历史命令:history
使用 history 查看列表,列出最近输入过的几百/几千条命令。通常配合 grep 使用。
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# history | grep "apt install"
202 sudo apt install nodejs npm
244 apt install unzip
247 apt install tealdeer
249 apt install tealdeer
274 apt install tealdeer
304 apt install mlocate
310 apt install ripgrep
314 history | grep "apt install"root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# history | grep "apt install"
202 sudo apt install nodejs npm
244 apt install unzip
247 apt install tealdeer
249 apt install tealdeer
274 apt install tealdeer
304 apt install mlocate
310 apt install ripgrep
314 history | grep "apt install"Ctrl + R (反向搜索)
- 在终端按
Ctrl + R。 - 输入你记得的几个字母(比如
dock)。 - 它会自动显示最近一条匹配的命令(比如
docker run -it ubuntu...)。 - 如果不是这条,再次按
Ctrl + R会显示次近的一条。 - 按
Enter直接执行,或者按右箭头进行修改。
文件夹导航
Zoxide
zoxide会通过学习的 cd 行为来变聪明。只需要正常浏览几个目录,就会记住。
- 智能跳转(模糊匹配): 假设以前去过
/home/panchant/projects/python/web-server,输入:它就会直接跳过去。bashz web # 或者 z server # 或者 z py webz web # 或者 z server # 或者 z py web
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# z mis
root@DESKTOP-Q64GDMO:/home/missing# z pan
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant#root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant# z mis
root@DESKTOP-Q64GDMO:/home/missing# z pan
root@DESKTOP-Q64GDMO:/mnt/c/Users/Panchant#- 普通跳转:
z完全兼容cd的用法。bashz .. # 回上一级 z /tmp # 去绝对路径 z - # 回上一次所在的目录z .. # 回上一级 z /tmp # 去绝对路径 z - # 回上一次所在的目录
交互式选择:zi
如果输入 z web,但有 web-server 和 web-client 两个目录,zoxide 会去权重最高的那一个。 如果想手动选,用 zi:
zi webzi web查看数据库:zoxide query
如果你想知道它到底记住了哪些路径以及权重:
zoxide query -l # 列出所有记录zoxide query -l # 列出所有记录Fzf
1. 安装
虽然 apt install fzf 也能装,但建议使用官方的 Git 方式安装。
原因:官方脚本会自动帮你配置好 Ctrl+R 和 Ctrl+T 这些快捷键,而 apt 安装的往往默认不开启这些功能,配置起来很麻烦。
# 1. 下载代码到主目录的 .fzf 文件夹
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
# 2. 运行安装脚本
~/.fzf/install# 1. 下载代码到主目录的 .fzf 文件夹
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
# 2. 运行安装脚本
~/.fzf/install安装过程中,它会问你几个问题(比如 Do you want to enable key-bindings?),按 y (Yes) 然后回车 即可。
安装完成后,让它立即生效
bashbash2. 快捷键
| 快捷键 | 功能 | 场景 |
|---|---|---|
Ctrl + R | 搜历史命令 | 最常用 按键后,随便输几个你记得的字母(如 dock),回车直接执行。 |
Ctrl + T | 搜文件 | 在写命令时(比如 vim ),突然想找个深层文件。按下它,选好文件,路径自动补全上屏。 |
Alt + C | 搜目录并跳转 | 类似于 cd,但你可以模糊搜索目录名,回车后直接跳进去。 |
3. 配合命令使用 (管道流) fzf 的本质是一个“过滤器”。可以把它接在任何命令后面。 我想用 vim 打开一个文件,但我懒得找路径:
vim $(fzf)vim $(fzf)$(fzf)会先运行 fzf,等你选定一个文件后,把它转换成文件名,传给vim。 我想看某个特定的环境变量:
env | fzfenv | fzf4. 配合 zoxide
- 命令:
zi - 效果:它会调用 fzf 的界面,显示你去过的所有目录。你可以在里面模糊搜索,选中后直接跳转。
5. 测试是否成功
- 输入
vim(然后按空格)。 - 不要回车,直接按
Ctrl + T。 - 随便输几个字母,选中一个文件,回车。
- 你会发现完整路径已经自动填在
vim后面了。 - 最后按回车打开文件。