主题 1 The Shell
课程概览与 shell · the missing semester of your cs education (missing-semester-cn.github.io)
Shell是什么?
一旦你想脱离可视化界面让你做的,然后做点别的事情,那么Shell将是你和计算机交互的最主要的方式之一。
可视化界面受限于,它只能做被设计出来的操作——比如你不能点击一个不存在的按钮或者是用语音输入一个还没有被录入的指令。这就是这门课介绍命令行工具和基于文本的工具的理由,shell则是你去做这些操作的地方。
在Windows和Linux可以找到成堆的终端(Terminal),这些是能显示Shell的文本窗口。其中普遍的是bash,或者叫Bourne Again Shell。由于bash的普遍性,这门课中将使用bash。
使用Shell
终端(Terminal)是你电脑上和shell交互的主要文本界面。
当你打开一个终端,你通常会在终端中看到这样的一行,称为命令行提示符(Shell Prompt)
[root@VM-8-17-centos ~]#
它告诉你,你的主机名是VM-8-17-centos
,你的用户名是root
,还有你当前所在的路径为~
(path)。
可以在终端上执行命令,通常是带着参数(argument)执行程序。参数一般是一些紧随程序名后面的,用空格分开的东西。
- date
date输入当前日期和时间
[root@VM-8-17-centos ~]# date
Sat Dec 17 01:04:35 CST 2022
- echo
echo打印出你传给它的参数
[root@VM-8-17-centos ~]# echo hello
hello
- 参数以空格分隔
如上所说,参数是被空格分隔的,如果传递一个多单词的参数,就必须用引号括起来,如:
[root@VM-8-17-centos ~]# echo "Hello Wrold"
Hello Wrold
这样echo程序会收到一个字符串参数Hello World
,中间还有一个空格。此外使用单引号也是可以的。
单双引号的区别将在bash scripting 再说
此外也可以使用转义符将空格转义,如:
[root@VM-8-17-centos ~]# echo Hello\ World
Hello World
关于如何给参数,变量转义,解析和加括号将在之后涉及
我们在创建目录或文件时,如果某个参数是带空格的,也需要使用引号转义或者用转义符将空格转义,否者shell将会将该参数识别成两个参数。
如下shell将my photo
识别成两个参数,创建了两个目录:
[root@VM-8-17-centos ~]# mkdir my photo
[root@VM-8-17-centos ~]# ls
my photo
正确的做法为:
[root@VM-8-17-centos ~]# mkdir "my photo"
[root@VM-8-17-centos ~]# ll
total 4
drwxr-xr-x 2 root root 4096 Dec 17 01:23 'my photo'
在Shell中导航
- 环境变量
你可能会好奇,当输入date或者echo等命令时,Shell怎么知道这些程序要做什么。
你的机器可能内嵌了终端程序,或者某些浏览器。同样的,电脑也内嵌了很多围绕终端工作的程序,这些程序位于你的文件系统(File System),Shell有办法在系统中搜索某个程序,然后执行。
当然,Shell不会在所有文件中进行搜索,那样效率太低了。
Shell借助一个叫做 环境变量(Environment Variable) 的东西来完成搜索。
环境变量就类似编程语言中的变量,Shell或者说bash本身就是一种程序设计语言。你输入的提示符(Prompt)不仅能带参运行程序,你也可以写入while循环,for循环,条件语句等,甚至可以定义函数,甚至变量。关于Shell Scripting的下一讲会有涉及
环境变量是Shell本就设定好的,无论何时打开shell都无需重新设置。一堆东西都会预先设置好,比如哪里是home目录,你的用户名是什么等。
- PATH变量
如下,当我们执行echo $PATH
时,将会输出一些电脑上的目录,这些目录就是Shell寻找程序时所查找的目录。这些目录以冒号分隔。
[root@VM-8-17-centos ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
当你输入一个程序名称时,电脑会在这个列表中的每个目录里,查找名字与你所输入的指令相同的一个程序或者文件。如果在这些目录中可以找到待运行的程序,程序可以正常运行,否则失败。
- which
如果我们想要知道电脑具体运行了哪一个目录里的程序,可以使用which指令。
[root@VM-8-17-centos ~]# which echo
/usr/bin/echo
[root@VM-8-17-centos ~]# which date
/usr/bin/date
- 路径
路径是用来描述你的计算机里文件位置的东西。
在Linux或者Mac Os上,路径被一连串的斜杠分隔,可以看到上面echo指令的路径起点在根目录/
(/ 即整个文件系统的最顶层)
在Windows里,路径以反斜杠\ 而非斜杠/分隔。
在Linux或Mac Os上,所有东西都在一个叫根(root)的空间的下面的某处。因此所有以斜杠开头/的路径都是绝对路径。
而在Windows下,每一个分区都有一个根,类似于C:\或者D:\,所以Windows里每一个驱动器(硬盘)下都有独立的一套文件系统的层次结构。
绝对路径:是可以绝对准确地确定一个文件的位置的路径
相对路径:是相对于你当前所在位置的路径
- pwd
打印工作目录(print working directory)
[root@VM-8-17-centos ~]# pwd
/root
你可以改变当前工作目录,所有的相对路径都是相对于当前工作目录的
- cd
change directory 改变当前工作目录
[root@VM-8-17-centos ~]# cd /home
[root@VM-8-17-centos home]# pwd
/home
shell提示只会给路径的最后一段名称,当然也可以通过设置是它总能显示当前的完整路径
- 特殊的目录
.
和..
.
表示当前目录,..
表示上一级(父)目录
[root@VM-8-17-centos lighthouse]# pwd
/home/lighthouse
[root@VM-8-17-centos lighthouse]# cd ../../..
[root@VM-8-17-centos /]# pwd
/
使用相对or绝对路径取决于哪个方便,但是如果有时候你需要运行某个程序或者写一个程序,它调用了类似echo或者date这样的程序,你希望它在哪个地方都能跑起来,要么你就只给出这个要被运行的程序的名字(让shell用path去找出它们在哪里),要么就需要给出绝对路径
一般来说程