MS1+2 shell 学习笔记/shell使用技巧
介绍
Missing Semester 1 和 2 的学习笔记。
Course View + the shell : https://missing.csail.mit.edu/2020/course-shell/
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
:也没怎么用过,好像是用来导出变量之类的东西。
输入输出流
一般每个进程都有三个主要的流:
- 标准输入流(STDIN),用于读入。
- 标准输出流(STDOUT),输出结果
标准错误流(STDERR),用于输出进程发生的错误。
<
: 重定义标准输入流。>
: 重定义标准输出流,输出前会清空目标文件,不存在则创建文件。(时间在所在命令执行之前,所以在某些指令中使用可能会涉及时机问题)。>>
: 重定义标准输出流,输出时扩展目标文件内容,不会清空,不存在则创建文件。|
: 将左边的标准输出作为右边的标准输入。- 每个进程都有三个主要的文件描述符:$0$ 标准输入,$1$ 标准输出,$2$ 标准错误,所以可以用
1>/>
来重定向标准输出,2>
重定向标准错误流,或者使用&>
将标准输入或输出一起重定向(也可以>file 2>&1
)。
表达式扩展
通配符:?/*
匹配一个/任意多个字符。例如:文件夹中有 bar,foo1,foo23
,那么 rm foo?
删除 foo1
,rm 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 | if [ expression_1 ] && [expression_2] ; |
for循环语句:
1 | for variable in list |
while循环:
1 | while [ expression ]; |
函数:
1 | function_name() { |
特殊含义的参数
$0
:脚本名。$1
to$9
:给脚本的第 $i$ 个参数。$@
:所有参数。$#
:参数数量。$?
:上一条命令的返回代码(在这个参数使用前的上一条命令,不是脚本前的)。$$
:当前脚本的进程标识数(PID)。!!
:上一条完整的指令,包括参数。(一种用处,在上一条指令因为权限不够执行失败时,用管理员再执行一次)$_
:上一条的最后一个参数。
工具/扩展推荐
- shellcheck (https://github.com/koalaman/shellcheck):检查你的 Bash 脚本的语法错误。
- TLDR (https://tldr.sh/):简化版的
man
,会提供所查询指令的一些比较常用的用法。 - fd (https://github.com/sharkdp/fd):语法更加人性化的
find
。 - locate ()
目前进度
第一课 note + 视频完成。
第二课 note 和视频都没完成。