初识 Linux Shell
学习的第一步,就是要找到 Linux 终端的所在位置。目前较常见的图形化终端有 Konsole、Gnome terminal、xterm 等几种。一般安装后在各个发行版的菜单中搜索即可找到。Gnome terminal 和 Konsole 基本是当前各大流行 Linux 发行版预装最多的终端应用,功能也非常强大好用。而 xterm 是世界上第一款图形化终端软件,xterm 软件包在 X Window 出现之前就有了。其对于老式哑终端的模仿非常到位,可以仿真各类老式哑终端的色彩等行为。所谓的哑终端就是传统的利用通信电缆(一般是一条多线束的串行电缆)连接到 Unix 系统上的一台显示器和一个键盘。关于各个图形化终端的各类配置,同学们可以自行慢慢摸索。
除了上述的图形化终端,在 Linux 出现的早期,没有图形化界面可供操作,当时通常的方式是使用一个简单的哑终端操作 Unix 系统。当今 2021 年,这种连接方式基本早已不存在了,但是你仍然可以模拟此种连接方式。Linux 系统启动后,它会自动创建出一些虚拟控制台。虚拟控制台是运行在 Linux 系统内存中的终端会话。通过按键组合ctrl + alt + (F1~F7),可以分别切换到多个不同的虚拟控制台。这种模式称作 Linux 控制台,它仿真了早期的硬接线控制台终端,而且是一种同 Linux 系统交互的直接接口。虚拟控制台一般也被称为 tty。tty 代表电传打字机(teletypewriter)。这是一个古老的名词,指的是一台用于发送消息的机器。
在开始使用 tty 后,你可以看到首先会让你输入要登录的用户名,输入用户名回车后会提示输入密码,需要注意的是,密码的输入是不会显示在屏幕上的,盲输完回车即可完成登录,屏幕不显示密码是正常的,不要以为自己的键盘坏了。
起步
在启动图形化终端后,你首先会看到一个待输入的命令提示符,类似 windows 系统中的 cmd。一般如下所示,显示了当前用户 ID 名 testuser,系统名为 archlinux。~这个波浪线代表你正处于 testuser 这个用户的个人目录下,路径为/home/testuser。$代表当前是已一个普通用户登陆,若为#则表示是以 root 帐户登陆。
testuser@archlinux:~$
你可能听说过 Linux 中有非常多的命令,都记住各个命令的用法是不现实的,所以第一步我们来学习的命令就是 man 命令:一个用来查询各个命令如何使用的命令。
在 ArchLinux 上,你首先需要安装man-db man-pages两个包,如果是第一次安装,最好执行一下如下命令,以便 man-db.service 建立-k 搜索参数需要使用的 db 索引。
$ sudo systemctl enable --now man-db #第一次执行时间会较长,可能会有几分钟 耐心等待
sudo 命令代表可以让当前用户暂时使用 root 权限执行此条命令。
比如,现在想查询 ls 命令的使用方式,那么输入执行如下命令即可
$ man ls
执行后你可以看到标题,描述,以及一大堆的信息。首先要知道,man 命令是用来速查某种命令使用方式的,不是用来各个详细阅读的(当然你有时间愿意读也没问题)。在这个界面你可以执行一些搜索操作,方式和在 vim 中类似,比如输入/斜杠加上你想搜索的单词进行搜索,n键跳到下一个匹配的位置等等。一般常规的查询一个命令的流程就是先看一下 Description 知道这个命令是干什么的,然后输入斜杠搜索一下你想查询的参数的含义,最后看完按q键退出。
在 man 页面的左上角,可以看到LS(1)的字样。这个(1)代表的是手册类型,下面列举一下各个数字所代表的类型意义。
- 1:可执行程序或 shell 命令
- 2:系统调用
- 3:库调用
- 4:特殊文件
- 5:文件格式与约定
- 6:游戏
- 7:概览、约定及杂项
- 8:超级用户和系统管理员命令
- 9:内核例程
上面有的部分现在看不懂也没关系,该懂的时候你自然就懂了。
一个命令偶尔会在多个内容区域都有对应的手册页。比如说,有个叫作 hostname(在 archlinux 中需要安装包inetutils) 的命令。手册页中既包括该命令的相关信息,也包括对系统主机名的概述。要想查看所需要的页面,对手册页中的第 1 部分而言,可以输入 man 1 hostname。对于手册页中的第 7 部分,就是输入 man 7 hostname。
除了 man 命令可以查询 Linux 命令的使用方式,info 命令也可以进行查询(在 archlinux 中需要安装包texinfo)。这里不再详细讲述 info 命令,因为 man 命令已经可以覆盖绝大多数内容。
另外,大多数命令都可以接受-help 或--help 选项。例如你可以输入 hostname --help 来查看帮助。
如果不记得命令名怎么办?可以使用关键字搜索手册页。语法是:man -k 关键字。例如,要查找与终端相关的命令,可以输入 man -k terminal。
除了万能的 man 命令,近几年还出现了一个非常流行的命令行帮助项目:tldr。其含义为太长不看的缩写。像它的名字一样,这个命令只输出某个命令的最简要的使用方式,对喜欢太长不看的人来说非常好用。在 archlinux 上可以直接通过 pacman -S tldr 进行安装。
$ tldr tar #查看tar命令的简明使用方式
若你出现如下错误,说明你的网络环境下,tldr 命令查询的 github raw 网址已经被 GFW 墙掉了。请使用全局代理或 proxychains 前缀,或添加 https_proxy 环境变量。
Error fetching from tldr: <urlopen error [Errno 111] Connection refused>
cd 漫游文件系统
当登录系统并获得 shell 命令提示符后,你通常位于自己的主目录中。一般情况下,你首先会想去逛逛主目录之外的其他地方。本节将告诉你如何使用 shell 命令来实现这个目标。
稍微了解 Linux 文件系统的话就会知道,一般来说一个完整的 Linux 文件路径可能是这样的:
/home/testuser/Documents/test.cpp
这种完整的路径被称为绝对路径,即从根路径/到目标文件的完整路径结构,含义为 testuser 这个用户家路径下的 Documents 目录下,有一个名为 test.cpp 的文件。想查看当前所处的位置的绝对路径,可以使用命令pwd
$ pwd/home/testuser/Documents/
与此对应的,另一个概念为相对路径。其代表当前路径为基准起点,对应的一个相对位置。比如当前你所处的路径为/home/testuser/Documents,此时想要去到 testuser 用户的桌面 /home/testuser/Desktop 路径下,用相对路径即可表示为
../Desktop
其中..为双点符,表示当前目录的父目录。另外一个常用标识符为.单点符,标识当前目录自身。
在文件系统中变更目录位置的命令为cd,可以接受绝对路径或相对路径作为参数
#绝对路径的例子$ cd /home/testuser/Documents/ #使用绝对路径的方式切换到/home/testuser/Documents/路径下#相对路径的例子$ cd ../Desktop #从/home/testuser/Documents/目录,使用相对路径的方式切换到/home/testuser/Desktop/路径下
一般来说,要视情况来使用相对路径或者绝对路径。在上述例子中,使用相对路径可以少输入很多内容。若此时想要切换到/etc 路径下,则明显使用绝对路径较为方便
$ cd /etc #如果使用绝对路径$ cd ../../../etc #如果使用相对路径
cd 命令可以直接使用,不加任何参数,此时会默认切换到当前用户的家目录下,如/home/testuser。在终端中,如果你能看到提示符最后有一个~波浪线,它代表的就是当前的路径是当前用户的家目录。
此外,另一个常用的用法是cd -。此命令可以切换到你上次所处的文件系统路径位置下。在需要返回上次路径的时候,此命令非常高效实用。
ls 查看文件信息
本节首先来学习一下查看文件与目录信息的相关命令。ls 命令最基本的形式会显示当前目录下的文件和目录。
注意,ls 命令输出的列表是按字母排序的(按列排序而不是按行排序)。可用带 -F 参数的 ls 命令轻松区分文件和目录。
$ ls -FDocuments/ Videos/Music/ my_script.sh*Desktop/ Pictures/testfile
F 参数在目录名后加了正斜线(/),以方便用户在输出中分辨它们。类似地,它会在可执行文件(比如上面的 my_script 文件)的后面加个星号,以便用户找出可在系统上运行的文件。
Linux 经常采用隐藏文件来保存配置信息。在 Linux 上,隐藏文件通常是文件名以点号开始的文件。这些文件并没有在默认的 ls 命令输出中显示出来,因此我们称其为隐藏文件。要把隐藏文件和普通文件及目录一起显示出来,就得用到 -a 参数。,使用ls -a,所有以点号开头的隐藏文件现在都显示出来了。
-R 参数是 ls 命令可用的另一个参数,叫作递归选项。它列出了当前目录下包含的子目录中的文件。如果目录很多,这个输出就会很长。注意,首先 -R 参数显示了当前目录下的内容,也就是之前例子中用户 home 目录下的那些文件。另外,它还显示出了用户 home 目录下所有子目录及其内容。如果当前路径下的目录有更多的子目录,-R 参数会继续进行遍历。正如你尝试的,如果目录结构很庞大,输出内容会变得很长。
命令行的多个选项一般并不一定要分开输入:ls -F -R -a。它们可以进行如下合并:ls -FRa。
在基本的输出列表中,ls 命令并未输出太多每个文件的相关信息。要显示附加信息,另一个常用的参数是 -l。-l 参数会产生长列表格式的输出,包含了目录中每个文件的更多相关信息。这种长列表格式的输出在每一行中列出了单个文件或目录。除了文件名,输出中还有其他有用信息。输出的第一行显示了在目录中包含的总块数(block)。在此之后,每一行都包含了关于文件(或目录)的下述信息:
$ ls -l总用量 44drwxr-xr-x 3 testuser testuser 4096 Dec 13 21:09 Androiddrwx--x---+ 2 testuser testuser 4096 Dec 17 13:02 Desktop #多出的加号代表ACLdrwxr-xr-x 5 testuser testuser 4096 Dec 10 15:08 Documentsdrwxr-xr-x 4 testuser testuser 4096 Dec 17 11:06 Downloadsdrwxr-xr-x 3 testuser testuser 4096 Dec 10 22:50 Gamesdrwxr-xr-x 3 testuser testuser 4096 Dec 11 18:54 Musicdrwxr-xr-x 4 testuser testuser 4096 Dec 14 22:50 Picturesdrwxr-xr-x 2 testuser testuser 4096 Dec 13 11:28 Videos
- 文件类型,比如目录(d)、文件(-)、字符型文件(c)或块设备(b);
- 文件的权限;
- 文件的硬链接总数;
- 文件属主的用户名;
- 文件属组的组名;
- 文件的大小(以字节为单位);
- 文件的上次修改时间;
- 文件名或目录名。
-l 参数是一个强大的工具。有了它,你几乎可以看到系统上任何文件或目录的大部分信息。在进行文件管理时,ls 命令的很多参数都能派上用场。如果在 shell 提示符中输入 man ls,就能看到可用来修改 ls 命令输出的参数有好几页。别忘了可以将多个参数结合起来使用。你不时地会发现一些参数组合不仅能够显示出所需的内容,而且还容易记忆,例如 ls -alF。
由前面的例子可知,默认情况下,ls 命令会输出目录下的所有非隐藏文件。有时这个输出会显得过多,当你只需要查看单个或者少数文件信息时更是如此。幸而 ls 命令还支持在命令行中定义过滤器(filter)。它会用过滤器来决定应该在输出中显示哪些文件或目录。这个过滤器就是一个进行简单文本匹配的字符串。可以在要用的命令行参数之后添加这个过滤器:当用户指定特定文件的名称作为过滤器时,ls 命令只会显示该文件的信息。有时你可能不知道要找的那个文件的确切名称。ls 命令能够识别标准通配符,并在过滤器中用它们进行模式匹配:
- 问号(?)代表一个字符;
- 星号(*)代表零个或多个字符。
在过滤器中使用星号和问号被称为文件扩展匹配(file globbing),指的是使用通配符进行模式匹配的过程。通配符正式的名称叫作元字符通配符(metacharacter wildcards)。除了星号和问号之外,还有更多的元字符通配符可用于文件扩展匹配,例如可以使用中括号:
$ ls -l my_scr[ai]pt-rw-rw-r-- 1 christine christine 0 May 21 13:25 my_scrapt-rwxrw-r-- 1 christine christine 54 May 21 11:26 my_script
在这个例子中,我们使用了中括号以及在特定位置上可能出现的两种字符:a 或 i。中括号表示一个字符位置并给出多个可能的选择。可以像上面的例子那样将待选的字符列出来,也可以指定字符范围,例如字母范围[a - i]:
$ ls -l f[a-i]ll-rw-rw-r-- 1 christine christine 0 May 21 13:44 fall-rw-rw-r-- 1 christine christine 0 May 21 13:44 fell-rw-rw-r-- 1 christine christine 0 May 21 13:44 fill
另外,可以使用感叹号(!)将不需要的内容排除在外:
$ ls -l f[!a]ll-rw-rw-r-- 1 christine christine 0 May 21 13:44 fell-rw-rw-r-- 1 christine christine 0 May 21 13:44 fill-rw-rw-r-- 1 christine christine 0 May 21 13:44 full
在进行文件搜索时,文件扩展匹配是一个功能强大的特性。它也可以用于 ls 以外的其他 shell 命令。随后的部分会有更多相关的例子。
文件的处理
touch 创建文件
touch 命令用于创建空白文件。如果作用于一个已有文件,可以更改其修改时间。如果只想改变访问时间,可用-a参数:
$ touch -a test_onels -l --time=atime test_one
如果只使用 ls -l 命令,并不会显示访问时间。这是因为默认显示的是修改时间。要想查看文件的访问时间,需要加入另外一个参数:--time=atime。有了这个参数,就能够显示出已经更改过的文件的访问时间。
cp 复制文件
复制文件的格式为:
$ cp source destination
当 source 和 destination 参数都是文件名时,cp 命令将源文件复制成一个新文件,并且以 destination 命名。新文件就像全新的文件一样,有新的修改时间。
如果目标文件已经存在,cp 命令并不会提醒这一点。最好是加上-i选项,强制 shell 询问是否需要覆盖已有文件。
也可以将文件复制到现有目录中。
$ cp -i test_one /home/christine/Documents/
新文件就出现在目录 Documents 中了,和源文件同名。
上面的例子在目标目录名尾部加上了一个正斜线(/),这表明 Documents 是目录而非文件。这有助于明确目的,而且在复制单个文件时非常重要。如果没有使用正斜线,子目录/home/christine/Documents 又不存在,就会有麻烦。在这种情况下,试图将一个文件复制到 Documents 子目录反而会创建一个名为 Documents 的文件,连错误消息都不会显示!
上一个例子采用了绝对路径,不过也可以使用相对路径。
本章在前面介绍了特殊符号可以用在相对文件路径中。其中的单点符(.)就很适合用于 cp 命令。记住,单点符表示当前工作目录。如果需要将一个带有很长的源对象名的文件复制到当前工作目录中时,单点符能够简化该任务。如果你的源对象名很长,使用单点符要比输入完整的目标对象名省事得多。
$ cp -i /etc/NetworkManager/NetworkManager.conf .
cp 命令的 -R 参数威力强大。可以用它在一条命令中递归地复制整个目录的内容:
$ ls -Fd *Scripts #-d选项只列出目录本身的信息,不列出其中的内容。一般可与 l 选项搭配显示目录自身详情$ cp -R Scripts/ Mod_Scripts
在执行 cp -R 命令之前,目录 Mod_Scripts 并不存在。它是随着 cp -R 命令被创建的,整个 Scripts 目录中的内容都被复制到其中。注意,在新的 Mod_Scripts 目录中,所有的文件都有对应的新日期。Mod_Scripts 目录现在已经成为了 Scripts 目录的完整副本。
也可以在 cp 命令中使用通配符:
$ cp *script Mod_Scripts/
该命令将所有以 script 结尾的文件复制到 Mod_Scripts 目录中。
[Tab]键 自动补全
如果你需要操作的文件/文件夹的名字很长,这正是制表键(Tab 键)自动补全挺身而出的时候。制表键自动补全允许你在输入文件名或目录名时按一下制表键,让 shell 帮忙将内容补充完整。
$ cp really_ridiculously_long_file_name Mod_Scripts/
在上面的例子中,我们输入了命令 cp really,然后按制表键,shell 就将剩下的文件名自动补充完整了。
使用制表键自动补全的的技巧在于要给 shell 足够的文件名信息,使其能够将需要文件同其他文件区分开。假如有另一个文件名也是以 really 开头,那么就算按了制表键,也无法完成文件名的自动补全。如果你的电脑有蜂鸣器,这时候你会听到蜂鸣器嘟的一声。要是再连按一下制表键,shell 就会列出所有以 really 开头的文件名。这个特性可以让你观察究竟应该输入哪些内容才能完成自动补全。
以上是对文件/文件夹的自动补全处理。如果希望对于 linux 命令也可以使用自动补全,在 Archlinux 上则需要额外安装包bash-completion。
mv 移动/重命名文件
在 Linux 中,重命名文件称为移动(moving)。mv 命令可以将文件和目录移动到另一个位置或重新命名。
$ mv fall fzll #重命名$ mv fzll Pictures/ #把文件fzll从/home/testuser移动到了/home/testuser/Pirctures
注意,mv 将文件名从 fall 更改为 fzll,但 inode 编号和时间戳保持不变。这是因为 mv 只影响文件名。和 cp 命令类似,也可以在 mv 命令中使用-i参数。这样在命令试图覆盖已有的文件时,你就会得到提示。
也可以使用 mv 命令移动文件位置并修改文件名称,这些操作只需一步就能完成:
$ mv /home/testuser/Pictures/fzll /home/testuser/fall
也可以使用 mv 命令移动整个目录及其内容:
$ mv Mod_Scripts Old_Scripts
rm 删除文件
bash shell 中删除文件的命令是 rm。rm 命令的基本格式非常简单。
$ rm -i fall
注意,-i 命令参数提示你是不是要真的删除该文件。bash shell 中没有回收站或垃圾箱,文件一旦删除,就无法再找回。因此,在使用 rm 命令时,要养成总是加入-i 参数的好习惯。也可以使用通配符删除成组的文件。别忘了使用-i 选项保护好自己的文件。
$ rm -i f?llrm: remove regular empty file "fell"? yrm: remove regular empty file "fill"? yrm: remove regular empty file "full"? y
rm 命令的另外一个特性是,如果要删除很多文件且不受提示符的打扰,可以用-f 参数强制删除。小心为妙!
ln 链接文件
链接文件是 Linu