一看就懂的Linux Shell的基础使用(一)
前言
最近在学习MIT的“计算机科学教育中缺失的一课(The Missing Semester of Your CS Education)”,这篇博客既是shell常用命令的备忘,也是这门课程的学习笔记。
shell
shell是操作系统为用户提供交互界面的命令行解释器的统称,例如Windows中的cmd就是一种shell。Bash 是其中最流行的一种。Bash 是 Bourne Again shell 的简称,其他的shell还有:zsh、fish、csh等。
你需要使用一个类Unix shell来完成文中所提到的操作。你可以:
- 使用安装了Linux的电脑
- 使用Linux虚拟机
- 使用WSL(Windows Subsystem for Linux)。
使用shell
进入shell,可以看到这样的一行提示:
1 | cyrus:~$ |
cyrus
代表当前用户的用户名,也可以使用echo $USER
来查看;~
代表当前所在路径,也可以使用pwd
来查看;$
是命令提示符,提示用户现在可以输入命令了。
~
是表示用户的家目录,非root用户的~
代表/home/$USER/
,而root用户的~
代表/root
。
直接输入一个程序的名称就可以运行,例如,Linux中有一个程序叫做date
,直接输入程序的名字,就可以运行它,这个程序将输出当前的时间:
1 | cyrus:~$ date |
程序可以附加参数,例如:
1 | cyrus:~$ echo hello |
这里的“hello”,就是传给程序echo
的参数。echo
程序的功能就是输出它的参数。参数和程序名、参数与参数之间都要使用空格隔开。如果参数里包含空格,可以用'
或"
将参数包裹起来,或者在空格前面加上一个反斜杠转义(如My\ Photos
会被转义成My Photos
)
shell怎么知道这些程序在哪里呢?其实shell会在$PATH
里面的路径寻找。这里的$PATH
和上面的$USER
都是shell中的变量,$
表示引用变量,提示shell把$变量名
替换成变量的值。$PATH
储存了多个路径,用“:”隔开,提示了shell去哪里找这个程序。你也可以使用which
来查找某一个程序的具体位置。输入程序的完整路径,也可以绕过$PATH
运行程序。
想要了解更多关于PATH的内容可以查看我的另一篇博客
1 | cyrus:~$ echo $PATH |
路径、pwd
、cd
在Linux和MacOS中,路径使用/
分隔,而在Windows中是\
。在Linux和MacOS中,路径从/
开始,代表根目录(包含了所有目录);在Windows中,路径从盘符开始,如C:\
。
以/
开头的路径叫绝对路径,否则就是相对路径。pwd
(print working directory的缩写)可以显示当前所在的绝对路径,cd
(change directory的缩写)可以改变当前所在路径。
.
代表当前所在目录,..
代表父目录。
1 | cyrus:~$ pwd |
注意输入cd命令后,“cyrus:”后面的路径改变了。
输入cd -
可以移动到上次所在的目录,相当于cd $OLDPWD
,非常方便。
1 | cyrus:/$ cd ~ |
常用的快捷键
最常用的两个
- 在shell中输入路径时,可以按Tab来自动补全文件名。
- 在shell中按↑/↓方向键,可以浏览历史命令。
也很重要的其他
- Ctrl + A 可以跳转到行首(助记:a是第一个字母,所以是行首)
- Ctrl + E 可以跳转到行尾(助记:e -> end)
- Ctrl + R 打开历史命令搜索,可以搜索之前使用过的指令,非常好用
- Ctrl + L 清屏,和使用
clear
命令效果相同 - Ctrl + C 强行终止当前程序
ls
ls
(list的缩写)可以列出当前目录下有什么:
1 | cyrus:/$ ls |
绝大多数程序都可以接受以-
开头的参数来改变程序的行为。例如,-h
或--help
一般会输出程序的帮助文本,如:
1 | cyrus:/$ ls --help |
显示ls
的帮助只能使用--help
而不能使用-h
,因为-h
已经被其他功能占用了
其中有一行
1 | -l use a long listing format |
根据这个内容,我们给ls
命令附加上-l
参数,有:
1 | cyrus:/home$ ls -l |
-l
参数非常有用,可以列出详细信息。
第一列的第一个字符是d
代表这是一个文件夹,下面列出了可能的类型:
标识符 | 类型 | 英文 |
---|---|---|
– | 常规文件 | regular file |
d | 文件目录 | directory |
c | 字符设备文件 | character device file |
b | 块设备文件 | block device file |
s | 本地socket文件 | local socket file |
p | 命名管道 | named pipe |
l | 符号链接 | symbolic link |
然后是九个字符描述了使用此文件的权限,三个字符为一组分成三组,分别表示文件持有者、文件持有组、和其他用户的权限。每组的三个字符中,r
、w
、x
分别代表read读、write写、execute执行权限,-
代表没有权限。
例如rwxr-xr--
代表文件持有者可以读、写、运行此文件,文件持有组可以读、运行此文件,其他用户只能读此文件。
第二列是有多少“ 硬链接 ”指向这个文件。
第三列和第四列,分别是文件持有者和文件持有组的名称
第五列是文件大小,默认以byte为单位,如果想要显示成“8M”,“13K”这种形式,只需要为ls
命令附加上-h
参数。
第六列就是文件的修改时间,即mtime。
最后一列就是文件名
man
man
可以显示一个命令的详细帮助文档,输入man ls
,会显示比ls --help
更加详细的命令使用帮助。
<
、>
、>>
、|
“< 文件"可以使用文件作为程序的输入,”> 文件"可以将程序的输出保存到文件中(不存在就会被创建)
1 | cyrus:~$ echo hello > hello.txt |
上面cat
的作用是将文件的内容展示到命令行输出。
“>”会覆盖原来存在的文件,如果文件不存在,会创建一个新文件并写入。
如果不想原来存在的文件被覆盖,而是想将新的内容加在文件末尾,可以使用“>>”
“|”长得像一个管道,它的作用就是像管道一样连接两个程序的输入与输出,它会把前面的程序的输出作为后面的程序的输入。
1 | cyrus:~$ ls -l / | tail -n1 |
这里的tail -n1
表示将取输入的最后一行并输出。
touch
、mkdir
、mv
、cp
、rm
touch 文件名
有两个作用:
mkdir 目录名
(make directory)可以创建新的文件夹,例:
1 | cyrus:~$ mkdir new_dir |
mv 源 目标
(move),可以用来移动文件/文件夹,也可以用来重命名文件/文件夹。
根据“源”和“目标”的不同,mv
会做出以下不同的行为:
- 移动:如果目标是一个存在的路径,则源会被移动到此目录下,名称不变。
- 重命名:否则,则源文件名会变为此目标文件名,如果存在同名文件,则会覆盖己存在的同名文件。
cp
(copy)的使用和mv
很像,会在目标目录下生成一个副本,如果需要复制一个文件夹,需要附加-r
参数(recursive 递归的缩写),来递归地拷贝文件夹下所有文件。
rm 目标
(remove)可以删除文件或目录,如果要删除的是一个目录,也需要附加-r
参数,来执行递归地删除。默认情况下,rm
命令需要你逐个确认你是否确定删除这个文件,附加-f
参数可以无需再次确认, 使用-f
时请保证你真的要删除,没有再次确定的机会了
#
#
表示注释,#
后的文本会被忽略。
1 | cyrus:~$ echo hello |
\
、'
、"
在shell中,有一些字符不能直接作为参数的一部分传递,例如!
、$
、
、#
、\
。
使用反斜杠\
可以转义单个字符,使其正常输出:
1 | cyrus:~$ echo hello$world |
使用单引号'
括起来,可以让字符串原样输出,不进行转义和替换
1 | cyrus:~$ echo 'hello\\world' |
使用双引号"
括起来的字符串仍然会被转义,参见Quoting。
1 | cyrus:~$ echo '$SHELL' |
sudo
Linux系统中有一个用户的身份是特殊的,那就是 root 用户,root用户拥有最高的权限,可以做几乎任何事情,直接登录到root用户是很危险的,因为你可能一不小心就利用root权限做出了一些破环性的操作(例如:误删除数据、全局修改了关键系统设置),因此,常常使用sudo 命令
(意思是 do as superuser),来使用超级用户权限执行命令,这样可以让你能再次确认你的操作无误。
当你输入一个命令,发现命令行输出了“Permission denied”,很可能就是你没有合适的权限执行这个命令,只要在原命令前加上sudo
就可以解决。
第一次sudo
时,会输出一段这样的提示:
1 | We trust you have received the usual lecture from the local System |
翻译如下:
1 | 我们确信您已经收到了本地系统管理员的例行讲解。 |
“With great power comes great responsibility.”,使用root权限时要时刻提醒自己,谨慎对待每一个命令。
下面有一个来自 MIT Missing Semester 的例子,指出了使用sudo
的一个常见误区:
例如,您笔记本电脑的屏幕亮度写在
brightness
文件中,它位于
1 >/sys/class/backlight通过将数值写入该文件,我们可以改变屏幕的亮度。现在,蹦到您脑袋里的第一个想法可能是:
1
2
3
4
5
6 >$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
>/sys/class/backlight/thinkpad_screen/brightness
>$ cd /sys/class/backlight/thinkpad_screen
>$ sudo echo 3 > brightness
>An error occurred while redirecting file 'brightness'
>open: Permission denied出乎意料的是,我们还是得到了一个错误信息。毕竟,我们已经使用了
sudo
命令!关于 shell,有件事我们必须要知道。|
、>
、和<
是通过 shell 执行的,而不是被各个程序单独执行。echo
等程序并不知道|
的存在,它们只知道从自己的输入输出流中进行读写。 对于上面这种情况, shell (权限为您的当前用户) 在设置sudo echo
前尝试打开 brightness 文件并写入,但是系统拒绝了 shell 的操作因为此时 shell 不是根用户。明白这一点后,我们可以这样操作:
1 >$ echo 3 | sudo tee brightness因为打开 /sys 文件的是 tee 这个程序,并且该程序以 root 权限在运行,因此操作可以进行。 这样您就可以在 /sys 中愉快地玩耍了,例如修改系统中各种LED的状态(路径可能会有所不同):
1 >$ echo 1 | sudo tee /sys/class/leds/input6::scrolllock/brightness
chmod
前面我们提到了文件的三种权限rwx
,使用chmod
可以调整这些权限。
chmod可以使用两种语法,字符串语法和数字语法。
字符串语法
- 用
ugoa
四个字母表示设置哪些人的权限 - 用
+-=
三个字母表示如何改变权限 - 用
rwx
表示什么权限
符号 | 含义 |
---|---|
u | user,文件的拥有者 |
g | group,文件拥有者所在的组的其他人 |
o | others,除了ug的其他人 |
a | all,所有人 |
+ | 添加权限 |
- | 减少权限 |
= | 设置权限 |
r | read,读取 |
w | write,写入 |
x | execute,执行 |
例如:
chmod ug+rw file
表示文件拥有者所在的组的所有人添加读取和写入file的权限。
chmod a-w file
表示所有人都不能写入file。
chmod ug=rwx,o=x file
表示文件拥有者所在的组的所有人都可以读、写、运行file,其他人只能运行file
八进制数字语法
一共有三种权限rwx
,,可以使用8个数字来表示某种人的权限,权限又分为针对三种人ugo
,于是,一个文件的权限可以用三个0-7的数字表示。
rwx
三种权限从高位到低位可以组成一个三位二进制数,0
代表没有这种权限,1
代表有,再将这个二进制数转化成八进制(或者十进制,在这里结果是一样的),就得到了对应的数字,下面列出了0-7对应的权限:
八进制 | 二进制 | 权限 |
---|---|---|
0 | 000 | — |
1 | 001 | –x |
2 | 010 | -w- |
3 | 011 | -wx |
4 | 100 | r– |
5 | 101 | r-x |
6 | 110 | rw- |
7 | 111 | rwx |
例如:
-
chmod 777 file
代表所有人都有file的所有权限 -
chmod 755 file
代表file的权限是rwxr-xr-x
755是创建新文件夹的默认权限 -
chmod 644 file
代表file的权限是rw-r--r--
644是创建新文件的默认权限
使用数字来设置权限,可以仅仅用三个字符就设置好每一个权限,非常方便快捷。
相关链接
MIT The Missing Semester of Your CS Education
GNU manual documents