(该系列文章大部分内容来源于MIT课程笔记,加入了个人的理解、原笔记中没有的细节和其他的需要理解的内容,公开课地址:https://www.bilibili.com/video/BV14E411J7n2?p=1)
下一讲:Shell工具与脚本
The Shell
1.Shell是什么?
如今的计算机有着多种多样的交互接口让我们可以进行指令的的输入,从炫酷的图像用户界面(GUI),语音输入甚至是AR/VR都已经无处不在。 这些交互接口可以覆盖80%的使用场景,但是它们也从根本上限制了您的操作方式——你不能点击一个不存在的按钮或者是用语音输入一个还没有被录入的指令。 为了充分利用计算机的能力,我们不得不回到最根本的方式,使用文字接口:Shell
。虽然各种平台支持不同的Shell,但是其核心功能都是一样的:它允许你执行程序,输入并获取某种半结构化的输出。
这里我们使用Bourne Again SHell, 简称 “bash” (现在流行的zsh是兼容bash的,MIT老师用的是bash,博主演示的是在Mac下使用zsh)
在mac终端切换bash和zsh:
切换到bash:chsh -s /bin/bash
或直接输入bash
切换到zsh:chsh -s /bin/zsh
或直接输入zsh
重启终端后有效(后面两个方法不需要重启)。
2.使用shell
当您打开终端时,您会看到一个提示符,它看起来一般是这个样子的:
missing:~$
这是shell最主要的文本接口。它告诉你,你的主机名是 missing 并且您当前的工作目录或者说您当前所在的位置是~ (表示 “home”)。 $符号表示您现在的身份不是root
用户(稍后会介绍)。在这个提示符中,您可以输入 命令 ,命令最终会被shell解析。最简单的命令是执行一个程序:
missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$ cal # 输出当月日历
九月 2020
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
missing:~$ df # 查看磁盘剩余空间的数量
missing:~$ free # 查看空闲内存的数量
echo
我们可以在执行命令的同时向程序传递 参数 :
missing:~$ echo hello
hello
missing:~$
上例中,我们让shell执行 echo
,同时指定参数hello,echo
程序将该参数打印出来。
echo
还可以将shell当做计算器使用,在算术表达式中空格并不重要,并且表达式可以嵌套:
echo $((expression))
举例:
➜ Downloads echo Five divided by two equals $((5/2))
Five divided by two equals 2
参数展开
shell是如何知道去哪里寻找 date
或 echo
的呢?其实,类似于Python or Ruby,shell是一个编程环境,所以它具备变量、条件、循环和函数。当你在shell中执行命令时,您实际上是在执行一段shell可以解释执行的简短代码。如果你要求shell执行某个指令,但是该指令并不是shell所了解的编程关键字,那么它会去咨询环境变量 $PATH
,它会列出当shell接到某条指令时,进行程序搜索的路径;叫做 “USER” 的变量包含你的用户名。
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
➜ Downloads echo $USER
lilhoe
当我们执行 echo
命令时,shell了解到需要执行 echo
这个程序,随后它便会在$PATH
中搜索由:
所分割的一系列目录,基于名字搜索该程序。当找到该程序时便执行(假定该文件是 可执行程序,后续课程将详细讲解)。确定某个程序名代表的是哪个具体的程序,可以使用 which
程序。我们也可以绕过 $PATH
,通过直接指定需要执行的程序的路径来执行该程序。
要查看有效的变量列表,可以试试这个:
printenv | less
引用
➜ Downloads echo this is a test
this is a test
➜ Downloads echo The total is $100.00
The total is .00
shell基于空格分割命令并进行解析,在第一个例子中,shell 利用单词分割删除掉 echo 命令的参数列表中多余的空格。在第二个 例子中,参数展开把 $1 的值替换为一个空字符串,因为 1 是没有定义的变量。shell 提供了一 种叫做引用的机制,来有选择地禁止不需要的展开。
-
双引号: 如果你把文本放在双引号中,shell 使用的特殊字 符,都失去它们的特殊含义,被当作普通字符来看待。有几个例外:
$
,\
(反斜杠),和‘
(上单引号)。这意味着单词分割(内嵌的空格也不会被当作界定符,它们成为参数的一部分)、路径名展开、波浪线展开和花括号展开都将失效,然而参数展开、 算术展开和命令替换仍然执行。使用双引号,我们可以处理包含空格的文件名(当然也可以不用双引号而用\
转义空格)。 -
单引号:禁止所有的展开。
# 无引用,双引号和单引号的比较
[me@linuxbox ~]$ echo text ~/*.txt {
a,b} $(echo foo) $((2+2)) $USER text
/home/me/ls-output.txt a b foo 4 me
[me@linuxbox ~]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER" text
~/*.txt {
a,b} foo 4 me
[me@linuxbox ~]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER' text
~/*.txt {
a,b} $(echo foo) $((2+2)) $USER
确定文件类型
- Linux关于文件名的重要规则:
-
以 “.” 字符开头的文件名是隐藏文件,
ls
命令不能列出它们,用ls -a
命令就可以了。当你创建帐号后,几个配置帐号的隐藏文件被放置在你的home目录下。稍后,我们会仔细研究一些隐藏文件,来定制你的系统环境。另外, 一些应用程序也会把它们的配置文件以隐藏文件的形式放在你的家目录下面。 -
Linux 没有“文件扩展名”的概念,不像其它一些系统。可以用你喜欢的任何 名字来给文件起名。文件内容或用途由其它方法来决定。虽然类 Unix 的操作 系统,不用文件扩展名来决定文件的内容或用途,但是有些应用程序会。
-
虽然 Linux 支持长文件名,文件名可能包含空格,标点符号,但标点符号仅限 使用“.”,“-”,下划线。最重要的是,不要在文件名中使用空格。如果你想表 示词与词间的空格,用下划线字符来代替。
基于上述第三点,我们需要确定文件类型,使用下面file
语句,打印出文件内容的简单描述:
file filename
# 举例:
~/Downloads file paper.tex
paper.tex: LaTeX 2e document text, ASCII text
3.在shell中导航
shell中的路径是一组被分割的目录,在 Linux 和 macOS 上使用 / 分割,而在Windows上是\。路径 /代表的是系统的根目录,所有的文件夹都包括在这个路径之下(Linux系统)。当前工作目录可以使用 pwd
命令来获取。此外,切换目录需要使用 cd
命令。在路径中,. 表示的是当前目录,而..
表示上级目录:
missing:~$ pwd
/home/missing
missing:~$ cd /home
missing:/home$ pwd
/home
missing:/home$ cd ..
missing:/$ pwd
/
missing:/$ cd ./home
missing:/home$ pwd
/home
missing:/home$ cd missing
missing:~$ pwd
/home/missing
missing:~$ ../../bin/echo hello
hello
通过cd -
命令可以回到上次的目录环境下,cd ~
默认回到根目录:
lilhoe@LilHoedeMacBook-Pro ~ % cd /Users/lilhoe/Downloads
lilhoe@LilHoedeMacBook-Pro Downloads % pwd
/Users/lilhoe/Downloads
lilhoe@LilHoedeMacBook-Pro Downloads % cd ~
lilhoe@LilHoedeMacBook-Pro ~ % pwd
/Users/lilhoe
lilhoe@LilHoedeMacBook-Pro ~ % cd -
~/Downloads
lilhoe@LilHoedeMacBook-Pro Downloads % pwd
/Users/lilhoe/Downloads
lilhoe@LilHoedeMacBook-Pro Downloads %
为了查看指定目录下包含哪些文件,我们使用ls
命令:
missing:~$ ls
missing:~$ cd ..
missing:/home$ ls
missing
missing:/home$ cd ..
missing:/$ ls
bin
boot
dev
etc
home
...
除非我们利用第一个参数指定目录,否则ls
会打印当前目录下的文件。大多数的命令接受标记和选项(带有值的标记),它们以- 开头,并可以改变程序的行为。通常,在执行程序时使用-h
或 -help</