介绍

Missing Semester 1 和 2 的学习笔记。

  1. Course View + the shell : https://missing.csail.mit.edu/2020/course-shell/

  2. Shell Tools and Scripting : https://missing.csail.mit.edu/2020/shell-tools/

主要讲了一些适用于 Bash(MacOS 和 Linux 的 默认shell)的知识,当然很多概念在其他 shell 中也有,不过名字可能不同。

笔记中不止涉及到了课程中讲的内容,还有些内容自己搜索补充了一下:

Bash条件等语句:https://blog.csdn.net/ceshiren_com/article/details/141930133

同时也懒得开一个新的文章了,干脆把其他的奇奇怪怪的 Bash 知识也放在这里了。

Shell 使用技巧

主要在 1. Course View + the shell 介绍,第二章也介绍了一点。

指令

  • date : 日期
  • echo : 输出后续的内容,例如:echo "test"
  • pwd : 输出 cmd 现在的工作目录。
  • cd : 进入某个文件夹,cd .. 进入上一级文件夹(可嵌套),cd HOME 到当前用户主文件夹,cd ~ 去到根目录。

    cd - 会让你回到上一次所在的目录,这在需要在两个目录间反复切换时很好用。

  • ls : 列出当前所有文件,ls dir 列出文件夹里面的所有文件和文件夹(不会递归)。

    ls -l 会列出文件夹内更加详尽的信息,左边的字符为:第一个字符是类型:$\text{d(文件夹)/-(文件)}$,后面有三组三个字符($\text{rwx}$),分别代表拥有者、拥有组、所有人的权限:

    | 符号 |文件| 文件夹 |
    |:——:|:—-:|:———:|
    | - | 没有对应权限 | 没有对应权限 |
    | r | 读取权限 | 读取文件列表 |
    | w | 写入权限 | 修改文件列表 |
    | x | 执行 | 进入文件夹的权限(需要当前和所有父文件夹的 x 权限) |$

    注:其实文件夹的权限可以看成是,对记录文件夹中文件信息的那个文件的权限。

  • man$(\text{manual})$ : 查询某个指令的用法(如果这个指令有 manual 界面的话)

  • mkdir : 创建文件夹
  • mv : 移动文件,mv source goal ,如果 goal 是文件夹,则会移动到里面,如果不是,则会改名。
  • which : 返回文件的路径
  • chmod : 给某个文件加减权限,chmod +x file 给 file 加可执行的权限(在下一节课写脚本的时候会用到)。
  • cp$(\text{copy})$ : 复制文件。
  • cat$(\text{capture})$ : 获取文件中的内容。
  • touch : 更新文件的更改时间为当前时间,不存在则创建一个空文件。
  • head/tail : 输出输入的开头或者结尾,-nk 输出 $k$ 行。
  • sudo/#$(\text{super do})$ : 用管理员权限进行某个指令。
  • find : 寻找该文件夹中符合条件的文件或文件夹(会递归)。
  • locate : 通过且只能通过文件名查找文件,查找速度更快,需要用 updatedb 维护数据库,find 更详细的对比
  • tee : 将标准输入既输入到文件中,也输入到标准输出中。
  • rm/rmdir : 移除文件/空文件夹。
  • curl:访问给定的 URL 并返回结果。
  • tee(T型管,一个进两个出):从输入流读取输出到输出流和文件中。
  • cut:切割输入流得到的内容。
  • xdg-open:用合适的程序打开一个文件。
  • diff:比较文件的不同。
  • source:我目前只用它来加载过脚本。
  • env:没怎么用过,但是在 shebang 行中使用可以提高脚本兼容性。
  • export:也没怎么用过,好像是用来导出变量之类的东西。

输入输出流

一般每个进程都有三个主要的流:

  1. 标准输入流(STDIN),用于读入。
  2. 标准输出流(STDOUT),输出结果
  3. 标准错误流(STDERR),用于输出进程发生的错误。

    • < : 重定义标准输入流。
    • > : 重定义标准输出流,输出前会清空目标文件,不存在则创建文件。(时间在所在命令执行之前,所以在某些指令中使用可能会涉及时机问题)。
    • >> : 重定义标准输出流,输出时扩展目标文件内容,不会清空,不存在则创建文件。
    • | : 将左边的标准输出作为右边的标准输入。
    • 每个进程都有三个主要的文件描述符:$0$ 标准输入,$1$ 标准输出,$2$ 标准错误,所以可以用 1>/> 来重定向标准输出,2> 重定向标准错误流,或者使用 &> 将标准输入或输出一起重定向(也可以 >file 2>&1 )。

表达式扩展

通配符:?/* 匹配一个/任意多个字符。例如:文件夹中有 bar,foo1,foo23 ,那么 rm foo? 删除 foo1rm foo23 删除 foo1,foo23

大括号:{} ,里面放上可能匹配的若干模式串,例如:*.{png,jpg} 用于匹配图片。

替换

command substitution:$(CMD) 会执行 CMD 然后将其输出替换掉这一部分。

process substitution: <(CMD) 会执行 CMD 然后将其输出放在一个临时文件,将临时文件的名字替换掉这一部分。例如:diff <(ls d1) <(ls d2) 就必须用这个替换而不能用上面的,因为上面的部分会用输出替换掉 $(ls d1) ,然后这条指令就变成了比较两个文件夹内所有文件里的内容,然后就偏离预期了。

计算表达式:使用 []/[[]] ,里面放表达式即可,两者的区别似乎是后者有更多语法但兼容性更差,具体区别 here

一些简称

  • $PATH : 所有环境变量,环境变量是系统在寻找可执行文件时会搜索的目录。
  • $HOME/~ : 表示用户的主文件夹 /home/user
  • / : 表示根目录,ls / 进入根目录,路径前面有没有 / 是区分相对路径和绝对路径的标志。

杂项

  • /sys 文件夹中会将内核参数以文件的形式展现,通过修改这些文件可以起到配置某些系统功能的作用,例如用亮度之类的。
    • /dev/null :可以理解为电子焚烧炉,不要的东西往里面丢就行了。
  • C-l 会让当前行到 shell 顶部,但并不会清空 shell ,他只会在前面填充大段的空白达到类似清空的效果。
  • 命令行前的 $ 表示现在处在用户环境,# 表示管理员环境,使用 sudo su/exit 进入/退出。
  • ; 隔开可以一行写多条指令。
  • 命令后加 \ 可以另开一行,' 可以开多行(在输入 ' 结束),; 可以一行输入多个命令。

Bash 脚本

主要在 2. Shell Tools and Scripting 介绍。

Shell 中和在脚本中能使用的语法基本一样,这里主要介绍一般只会(不是只能)在脚本中使用的语法。

杂项

变量:foo=bar,这样会得到一个值为字符串 bar 的变量 foo$foo 引用该变量。

shebang 行 :在脚本的第一行,用于标明这个脚本使用的执行程序。例如一般 Bash 脚本的 shebang 行:#!/bin/bash

使用 env 来写 shebang 行可以提高脚本兼容性,例:#!/usr/bin/env python ,会让程序使用 env 去 Path 中寻找 Python 的可执行程序作为这个脚本的执行程序。

source A 会让 CMD 加载脚本 A ,这会运行其中的指令,和 ./A 的区别在于,前者在当前环境,而后者是新开了一个环境,所以脚本中如果有 cd 之类的指令,前者会影响当前 shell ,后者不会,包括定义的函数和参数也是。

条件/循环语句

条件语句:

1
2
3
4
5
6
7
8
9
10
if [ expression_1 ] && [expression_2] ;
then
statements
elif [ expression_3 ] || [expression_4] ;
then
statements
else
statements
fi
# true/false 会一直返回对应的布尔值

for循环语句:

1
2
3
4
5
6
7
8
9
for variable in list
do
commands
done
#或
for (( expression1; expression2; expression3 )) #Ex:for ((i=1; i<=10; i++))
do
commands
done

while循环:

1
2
3
4
while [ expression ];
do
commands;
done

函数:

1
2
3
function_name() {
commands
}

特殊含义的参数

  • $0:脚本名。
  • $1 to $9:给脚本的第 $i$ 个参数。
  • $@:所有参数。
  • $#:参数数量。
  • $?:上一条命令的返回代码(在这个参数使用前的上一条命令,不是脚本前的)。
  • $$:当前脚本的进程标识数(PID)。
  • !!:上一条完整的指令,包括参数。(一种用处,在上一条指令因为权限不够执行失败时,用管理员再执行一次)
  • $_:上一条的最后一个参数。

工具/扩展推荐

目前进度

第一课 note + 视频完成。

第二课 note 和视频都没完成。