描述linux文件系统的层次结构概念
目标
完成这一部分后,你能够描述Linux如何组织文件,以及文件系统层次结构中各种目录的作用。
文件系统的层次结构
Linux系统中的所有文件都存储在文件系统中,文件系统被组织成一棵倒置的目录树,称为文件系统层次结构。这个树是倒置的,因为树的根部在层次结构的顶端,而目录和子目录的分支在根部以下延伸。
Figure 3.1: Significant file-system directories in Red Hat Enterprise Linux 8
/目录是位于文件系统层次结构的顶部的根目录。在文件名中,/字符也被用作目录分隔符。例如,如果 etc 是 / 目录的一个子目录,你可以把这个目录称为 /etc。同样,如果 /etc 目录中包含一个名为 issue 的文件,你可以将该文件称为 /etc/issue。
/的子目录起到标准化的作用,按类型和作用组织文件。这使得查找文件更容易。例如,在根目录下,子目录/boot是用来存储启动系统所需的文件。
下面的术语有助于描述文件系统目录内容:
静态(static)内容保持不变,直到被明确编辑或重新配置。
动态( dynamic )或(variable)可变内容可由主动进程修改或附加。
持久(persistent) 内容在重启之后任然有效,比如配置文件。
运行时(runtime)内容是进程或系统特定的内容,通过重启删除。
下表按名称和目的列出了系统中一些最重要的目录。
重要的 Red Hat Enterprise Linux 目录
路径
作用
/usr
已安装的软件、共享库、包含文件和只读程序数据。
重要的子目录包括:
/usr/bin: 用户命令
/usr/sbin:系统管理命令
/usr/local:本地定制的软件
/etc
配置文件目录
/var
存放数据文件,如数据库、缓存目录、日志文件、打印机打印出来的文档和网站内容等
/run
进程的运行信息。其中包括进程ID文件和锁文件等。这个目录的内容会在重启时重新创建。这个目录整合了Red Hat Enterprise Linux早期版本中的/var/run和/var/lock。
/home
普通用户存储个人数据和配置文件的地方。
/root
管理员超级用户的主目录,root。
/tmp
可写的临时文件空间。10天内没有被访问、更改或修改的文件会自动从这个目录中删除。另一个临时目录/var/tmp,在这个目录中,超过30天没有被访问、更改或修改的文件会被自动删除。
/boot
启动过程中需要的文件。
/dev
包含了系统用来访问硬件的特殊设备文件。
在Red Hat Enterprise Linux 7及以后的版本中,/中的四个旧目录的内容与位于/usr中的对应目录完全相同:
/bin和 /usr/bin
/sbin 和/usr/sbin
/lib 和 /usr/lib
/lib64 和 /usr/lib64
在Red Hat Enterprise Linux的早期版本中,这些是不同的目录,包含不同的文件。
在Red Hat Enterprise Linux 7及以后的版本中,/中的目录是与/usr中的匹配目录的符号链接。
指定文件名
目标
完成本节内容后,能够指定文件相对于当前工作目录的位置,并按绝对位置,确定和更改工作目录,并列出目录的内容。
绝对路径和相对路径
Figure 3.2: The common file browser view (left) is equivalent to the top-down view (right).
一个文件或目录的路径指定了它在文件系统中的唯一位置。在文件路径之后,会遍历一个或多个子目录,以前向斜线(/)分隔,直到到达目的地。目录也称为文件夹,包含其他文件和其他子目录。它们可以像文件一样被引用。
作为Linux文件名支持空格字符。但是,空格也被shell用来分隔命令行中的选项和参数。如果你输入的命令中包含了一个文件名中的空格,shell可能会误认为你要在空格处启动一个新的文件名或其他参数。可以通过将文件名放在引号中来避免这种情况。但是,命名尽量避免空格。
绝对路径
绝对路径是一个完全限定的名称,指定了文件在文件系统层次结构中的确切位置。它从根目录(/)开始,并指定了必须遍历的每个子目录才能到达特定的文件。文件系统中的每一个文件都有一个唯一的绝对路径名,用一个简单的规则来识别。路径名中的第一个字符为前斜线(/)的路径名就是绝对路径名。例如,系统消息日志文件的绝对路径名是/var/log/ messages。绝对路径名可能比较长,所以文件也可以相对于shell提示符的当前工作目录。
当前工作目录和相对路径
当用户登录并打开命令窗口时,初始位置通常是用户的主目录。系统进程也有一个初始目录。用户和进程根据需要导航到其他目录;工作目录或当前工作目录指的是它们的当前位置。
与绝对路径一样,相对路径也是标识一个唯一的文件,只指定从工作目录到达文件所需的路径。识别相对路径名有一个简单的规则。路径名的第一个字符中除了前斜线以外的任何东西都是相对路径名。在/var目录下的用户可以将消息日志文件相对地称为log/messages。
Linux 文件系统,包括但不限于 ext4、XFS、GFS2 和 GlusterFS,都是区分大小写的。在同一目录下创建 FileCase.txt 和 fileCase.txt 会产生两个唯一的文件。
非Linux文件系统的工作方式可能不同。例如,VFAT、微软的NTFS和苹果的HFS+都有保留大小写的行为。虽然这些文件系统对大小写不敏感,但它们确实以创建文件时使用的原始大写显示文件名。因此,如果你试图在VFAT文件系统上创建前面的例子中的文件,两个名字都会被视为指向同一个文件,而不是两个不同的文件。
路径
pwd命令会显示该shell当前工作目录的完整路径名。ls命令列出指定目录的目录内容,如果没有给出目录,则列出当前工作目录的目录内容。
[user@host ~]$ pwd
/home/user
[user@host ~]$ ls
Desktop Documents Downloads Music Pictures Public Templates Videos
[user@host ~]$
使用 cd 命令来改变你的 shell 的当前工作目录。如果你没有指定任何参数,它将会更改到你的主目录。
在下面的例子中,用cd命令混合使用绝对路径和相对路径来改变shell的当前工作目录。
[user@host ~]$ pwd
/home/user
[user@host ~]$ cd Videos
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd /home/user/Documents
[user@host Documents]$ pwd
/home/user/Documents
[user@host Documents]$ cd
[user@host ~]$ pwd
/home/user
[user@host ~]$
正如你在前面的例子中看到的,默认的shell提示符也会显示当前工作目录的绝对路径的最后一个目录。例如,对于/home/user/Videos,只显示Video。当你当前的工作目录是你的主目录时,提示符会显示"~"。
touch命令通常会将文件的时间戳更新为当前的日期和时间,而不会以其他方式修改文件。这对于创建空文件很有用,可以用于练习,因为 "touch "不存在的文件名会导致文件被创建。在下面的例子中,touch命令会在Documents 和Videos 子目录中创建练习文件。
[user@host ~]$ touch Videos/blockbuster1.ogg
[user@host ~]$ touch Videos/blockbuster2.ogg
[user@host ~]$ touch Documents/thesis_chapter1.odf
[user@host ~]$ touch Documents/thesis_chapter2.odf
[user@host ~]$
ls 命令有多个选项来显示文件的属性。最常见和有用的是-l(长列表格式)、-a(所有文件,包括隐藏文件)和-R(递归,包含所有子目录的内容)。
[user@host ~]$ ls -l
total 15
drwxr-xr-x. 2 user user 4096 Feb 7 14:02 Desktop
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Documents
drwxr-xr-x. 3 user user 4096 Jan 9 15:00 Downloads
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Music
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Pictures
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Public
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Templates
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Videos
[user@host ~]$ ls -la
total 15
drwx------. 16 user user 4096 Feb 8 16:15 .
drwxr-xr-x. 6 root root 4096 Feb 8 16:13 ..
-rw-------. 1 user user 22664 Feb 8 00:37 .bash_history
-rw-r--r--. 1 user user 18 Jul 9 2013 .bash_logout
-rw-r--r--. 1 user user 176 Jul 9 2013 .bash_profile
-rw-r--r--. 1 user user 124 Jul 9 2013 .bashrc
drwxr-xr-x. 4 user user 4096 Jan 20 14:02 .cache
drwxr-xr-x. 8 user user 4096 Feb 5 11:45 .config
drwxr-xr-x. 2 user user 4096 Feb 7 14:02 Desktop
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Documents
drwxr-xr-x. 3 user user 4096 Jan 25 20:48 Downloads
drwxr-xr-x. 11 user user 4096 Feb 6 13:07 .gnome2
drwx------. 2 user user 4096 Jan 20 14:02 .gnome2_private
-rw-------. 1 user user 15190 Feb 8 09:49 .ICEauthority
drwxr-xr-x. 3 user user 4096 Jan 9 15:00 .local
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Music
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Pictures
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Public
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Templates
drwxr-xr-x. 2 user user 4096 Jan 9 15:00 Videos
[user@host ~]$
列表顶部的两个特殊目录指的是当前目录(.)和父目录(..)。这些特殊目录存在于系统的每个目录中。
[user@host ~]$ ls -R
.:
Desktop Documents Downloads Music Pictures Public Templates Videos
./Desktop:
./Documents:
thesis_chapter1.odf thesis_chapter2.odf
./Downloads:
./Music:
./Pictures:
./Public:
./Templates:
./Videos:
blockbuster1.ogg blockbuster2.ogg
[user@host ~]$
cd命令有很多选项。其中有几个是非常有用的,值得我们尽早练习并经常使用。cd - 变更到之前的目录;用户之前所在的目录是当前目录。下面的例子说明了这种行为,在两个目录之间交替执行,这在处理一系列类似的任务时非常有用。
[user@host ~]$ cd Videos
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd /home/user/Documents
[user@host Documents]$ pwd
/home/user/Documents
[user@host Documents]$ cd -
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd -
[user@host Documents]$ pwd
/home/user/Documents
[user@host Documents]$ cd -
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd
[user@host ~]$
cd ..命令使用..向上移动一级到父目录,不需要知道确切的父目录名。另一个隐藏目录(.)在命令中指定了当前位置为源或目标参数的命令中的当前目录,避免了键入目录的绝对路径名。
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd .
[user@host Videos]$ pwd
/home/user/Videos
[user@host Videos]$ cd ..
[user@host ~]$ pwd
/home/user
[user@host ~]$ cd ..
[user@host home]$ pwd
/home
[user@host home]$ cd ..
[user@host /]$ pwd
/
[user@host /]$ cd
[user@host ~]$ pwd
/home/user
[user@host ~]$
使用命令行工具管理文件
目标
完成本节内容后,你能够创建、复制、移动和删除文件和目录。
命令行文件管理
要管理文件,你需要能够创建、删除、复制和移动文件。你还需要将它们逻辑地组织到目录中,你也需要能够创建、删除、复制和移动目录。
下表总结了一些最常用的文件管理命令。本节的其余部分将详细讨论如何使用这些命令。
常用的文件管理命令
作用
命令
创建目录
mkdir directory
复制文件
cp file new-file
复制目录
cp -r directory new-directory
移动或重命名文件或目录
mv file new-file
移除文件
rm file
删除目录
rm -r directory
删除空目录
rmdir directory
创建目录
mkdir命令可以创建一个或多个目录或子目录。它的参数是一个到你要创建的目录的路径列表。
如果目录已经存在,或者你试图在一个不存在的目录中创建一个子目录,那么mkdir命令会创建失败。-p (parent) 选项会为请求的目标创建缺失的父目录。在使用 mkdir -p 命令时要谨慎使用,因为拼写错误可能会在不产生错误信息的情况下创建出不想要的目录。
在下面的例子中,假设你正试图在名为Watched的Videos目录中创建一个目录,但你不小心在mkdir命令中遗漏了Videos中的字母 "s"。
[user@host ~]$ mkdir Video/Watched
mkdir: cannot create directory `Video/Watched': No such file or directory
mkdir命令失败的原因是Videos拼写错误,Video目录不存在。如果你使用了mkdir命令中的-p选项,就会创建Video目录,这与你的意图不符,而Watched子目录也会被创建在错误的目录中。
在正确拼写出视频父目录后,创建Watched子目录将成功。
[user@host ~]$ mkdir Videos/Watched
[user@host ~]$ ls -R Videos
Videos/:
blockbuster1.ogg blockbuster2.ogg Watched
Videos/Watched:
在下面的例子中,文件和目录被组织在/home/user/Documents目录下。使用mkdir命令和目录名列表来创建多个目录。
[user@host ~]$ cd Documents
[user@host Documents]$ mkdir ProjectX ProjectY
[user@host Documents]$ ls
ProjectX ProjectY
使用mkdir -p命令和每个子目录名的相对路径来创建多个带子目录的父目录。
[user@host Documents]$ mkdir -p Thesis/Chapter1 Thesis/Chapter2 Thesis/Chapter3
[user@host Documents]$ cd
[user@host ~]$ ls -R Videos Documents
Documents:
ProjectX ProjectY Thesis
Documents/ProjectX:
Documents/ProjectY:
Documents/Thesis:
Chapter1 Chapter2 Chapter3 Documents/Thesis/Chapter1:
Documents/Thesis/Chapter2:
Documents/Thesis/Chapter3:
Videos: blockbuster1.ogg blockbuster2.ogg Watched
Videos/Watched:
最后的mkdir命令用一个命令创建了三个ChapterN子目录。其中-p选项创建了缺失的父目录Thesis。
复制文件
cp命令复制一个文件,在当前目录或指定的目录中创建一个新文件。它也可以将多个文件复制到一个目录中。
[user@host ~]$ cd Videos
[user@host Videos]$ cp blockbuster1.ogg blockbuster3.ogg
[user@host Videos]$ ls -l
total 0
-rw-rw-r--. 1 user user 0 Feb 8 16:23 blockbuster1.ogg
-rw-rw-r--. 1 user user 0 Feb 8 16:24 blockbuster2.ogg
-rw-rw-r--. 1 user user 0 Feb 8 16:34 blockbuster3.ogg
drwxrwxr-x. 2 user user 4096 Feb 8 16:05 Watched
[user@host Videos]$
当用一个命令复制多个文件时,最后一个参数必须是一个目录。被复制的文件在新的目录中保留其原始名称。如果目标目录中存在相同名称的文件,那么现有的文件将被覆盖。默认情况下,cp不会复制目录,而是忽略这些目录。
在下面的例子中,列出了两个目录,即Thesis和ProjectX。只有最后一个参数,ProjectX作为目标目录是有效的。Thesis目录被忽略了。
[user@host Videos]$ cd ../Documents
[user@host Documents]$ cp thesis_chapter1.odf thesis_chapter2.odf Thesis ProjectX
cp: omitting directory `Thesis'
[user@host Documents]$ ls Thesis ProjectX
ProjectX:
thesis_chapter1.odf thesis_chapter2.odf
Thesis:
Chapter1 Chapter2 Chapter3
在上面cp命令中,Thesis 目录复制失败,但sis_chapter1.odf和sis_chapter2.odf文件复制成功。
如果你想将文件复制到当前工作目录,可以使用特殊的.目录。
[user@host ~]$ cp /etc/hostname .
[user@host ~]$ cat hostname
host.example.com
[user@host ~]$
使用copy命令的-r(递归)选项,将Thesis目录及其内容复制到ProjectX目录。
[user@host Documents]$ cp -r Thesis ProjectX
[user@host Documents]$ ls -R ProjectX
ProjectX:
Thesis thesis_chapter1.odf thesis_chapter2.odf
ProjectX/Thesis:
Chapter1 Chapter2 Chapter3
ProjectX/Thesis/Chapter1:
ProjectX/Thesis/Chapter2:
thesis_chapter2.odf
ProjectX/Thesis/Chapter3:
移动文件
mv 命令可以将文件从一个位置移动到另一个位置。如果你把文件的绝对路径看作是文件的全名,那么移动一个文件就等于重命名一个文件。文件的内容保持不变。
使用 mv 命令重命名一个文件。
[user@host Videos]$ cd ../Documents
[user@host Documents]$ ls -l thesis*
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter1.odf
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter2.odf
[user@host Documents]$ mv thesis_chapter2.odf thesis_chapter2_reviewed.odf
[user@host Documents]$ ls -l thesis*
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter1.odf
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter2_reviewed.odf
使用mv命令将文件移动到不同目录。
[user@host Documents]$ ls Thesis/Chapter1
[user@host Documents]$
[user@host Documents]$ mv thesis_chapter1.odf Thesis/Chapter1
[user@host Documents]$ ls Thesis/Chapter1
thesis_chapter1.odf
[user@host Documents]$ ls -l thesis*
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter2_reviewed.odf
移除文件和目录
rm 命令会删除文件。默认情况下,rm 不会删除包含文件的目录,除非你添加了 -r 或 --recursive 选项。
在删除一个文件或目录之前,最好先验证一下你当前的工作目录。
[user@host Documents]$ pwd
/home/student/Documents
使用 rm 命令从工作目录中删除一个文件。
[user@host Documents]$ ls -l thesis*
-rw-rw-r--. 1 user user 0 Feb 6 21:16 thesis_chapter2_reviewed.odf
[user@host Documents]$ rm thesis_chapter2_reviewed.odf
[user@host Documents]$ ls -l thesis*
ls: cannot access 'thesis*': No such file or directory
如果你试图使用 rm 命令删除一个目录而不使用 -r 选项,该命令将失败。
[user@host Documents]$ rm Thesis/Chapter1
rm: cannot remove `Thesis/Chapter1': Is a directory
使用 rm -r 命令删除一个子目录及其内容。
[user@host Documents]$ ls -R Thesis
Thesis/:
Chapter1 Chapter2 Chapter3
Thesis/Chapter1:
thesis_chapter1.odf
Thesis/Chapter2:
thesis_chapter2.odf
Thesis/Chapter3:
[user@host Documents]$ rm -r Thesis/Chapter1
[user@host Documents]$ ls -l Thesis
total 8
drwxrwxr-x. 2 user user 4096 Feb 11 12:47 Chapter2
drwxrwxr-x. 2 user user 4096 Feb 11 12:48 Chapter3
rm -r命令会先遍历每个子目录,在删除每个目录之前单独删除它们的文件。你可以使用 rm -ri 命令在删除前交互式地提示确认。这与使用 -f 选项本质上是相反的,后者是在不提示用户确认的情况下强制删除。
[user@host Documents]$ rm -ri Thesis
rm: descend into directory `Thesis'? y
rm: descend into directory `Thesis/Chapter2'? y
rm: remove regular empty file `Thesis/Chapter2/thesis_chapter2.odf'? y
rm: remove directory `Thesis/Chapter2'? y
rm: remove directory `Thesis/Chapter3'? y
rm: remove directory `Thesis'? y
[user@host Documents]$
[user@host Documents]$ pwd
/home/student/Documents
[user@host Documents]$ rmdir ProjectY
[user@host Documents]$ rmdir ProjectX
rmdir: failed to remove `ProjectX': Directory not empty
[user@host Documents]$ rm -r ProjectX
[user@host Documents]$ ls -lR
.:
total 0
[user@host Documents]$
在文件之间建立链接
目标
完成本节内容后,你能够使用硬链接和符号(或 "软 "链接)使多个文件名引用同一个文件。
管理文件之间的链接
硬链接和软链接
可以创建多个指向同一个文件的名称。有两种方法:通过创建指向文件的硬链接,或者通过创建指向文件的软链接(有时称为符号链接)。两种方法各有优缺点。
创建硬链接
每个文件从其初始名称到文件系统中的数据,都是由一个单一的硬链接开始的。当你创建一个新的硬链接到一个文件时,你会创建另一个指向相同数据的名称。新的硬链接的作用与原始文件名完全相同。一旦创建后,你无法分辨新的硬链接和文件的原始名称之间的区别。
你可以用ls -l命令来查找一个文件是否有多个硬链接。它报告的内容之一是每个文件的链接数,即文件的硬链接数量。
[user@host ~]$ pwd
/home/user
[user@host ~]$ ls -l newfile.txt
-rw-r--r--. 1 user user 0 Mar 11 19:19 newfile.txt
在前面的例子中,newfile.txt的链接数是1,它有一个绝对路径,那就是/home/user/newfile.txt。
你可以使用ln命令来创建一个新的硬链接(另一个名称),指向一个现有的文件。该命令至少需要两个参数,一个是指向现有文件的路径,另一个是指向你要创建的硬链接的路径。
下面的示例为/tmp目录下的现有文件newfile.txt创建一个名为newfile-link2.txt的硬链接。
[user@host ~]$ ln newfile.txt /tmp/newfile-hlink2.txt
[user@host ~]$ ls -l newfile.txt /tmp/newfile-hlink2.txt
-rw-rw-r--. 2 user user 12 Mar 11 19:19 newfile.txt
-rw-rw-r--. 2 user user 12 Mar 11 19:19 /tmp/newfile-hlink2.txt
如果你想知道两个文件是否是彼此的硬链接,一种方法是使用ls命令的-i选项来列出文件的inode号。如果两个文件都在同一个文件系统中(稍后讨论),并且它们的inode号相同,那么这两个文件就是指向同一个数据的硬链接。
[user@host ~]$ ls -il newfile.txt /tmp/newfile-hlink2.txt
8924107 -rw-rw-r--. 2 user user 12 Mar 11 19:19 newfile.txt
8924107 -rw-rw-r--. 2 user user 12 Mar 11 19:19 /tmp/newfile-hlink2.txt
即使原始文件被删除,只要至少有一个硬链接存在,文件的内容仍然可用。只有当最后一个硬链接被删除时,数据才会从存储中删除。
[user@host ~]$ rm -f newfile.txt
[user@host ~]$ ls -l /tmp/newfile-hlink2.txt
-rw-rw-r--. 1 user user 12 Mar 11 19:19 /tmp/newfile-hlink2.txt
[user@host ~]$ cat /tmp/newfile-hlink2.txt
Hello World
硬链接的局限性
硬链接有一些限制。首先,硬链接只能在普通文件中使用。你不能使用ln来创建一个硬链接到一个目录或特殊文件。
其次,只有当两个文件都在同一个文件系统中时,才能使用硬链接。文件系统的层次结构可以由多个存储设备组成。根据系统的配置,当你换到一个新的目录时,该目录及其内容可能会被存储在不同的文件系统中。
你可以使用 df 命令来列出不同文件系统中的目录。例如,你可能会看到下面这样的输出。
[user@host ~]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 886788 0 886788 0% /dev
tmpfs 902108 0 902108 0% /dev/shm
tmpfs 902108 8696 893412 1% /run
tmpfs 902108 0 902108 0% /sys/fs/cgroup /dev/mapper/rhel_rhel8--root 10258432 1630460 8627972 16% /
/dev/sda1 1038336 167128 871208 17% /boot
tmpfs 180420 0 180420 0% /run/user/1000
[user@host ~]$
两个不同 "挂载 "目录中的文件及其子目录在不同的文件系统中。这个例子中的系统,你可以在/var/tmp/link1和/home/user/file之间建立一个硬链接,因为它们都是/的子目录。但你不能在/boot/test/badlink和/home/user/file之间创建一个硬链接,因为第一个文件在/boot的子目录中挂载在/dev/sda1,而第二个文件是/的子目录挂载到/dev/mapper/rhel_rhel8--root。
创建软连接
ln -s命令会创建一个软链接,也叫 "符号链接"。软链接不是普通的文件,而是一种特殊类型的文件,它指向现有的文件或目录。
软链接比硬链接有一定的优势:
它们可以将不同文件系统上的两个文件连接起来。
它们可以指向一个目录或特殊文件,而不仅仅是普通文件。
在下面的例子中,ln -s命令用于为现有的文件/home/user/newfile-link2.txt创建一个新的软链接,该文件将被命名为/tmp/newfile-symlink.txt。
[user@host ~]$ ln -s /home/user/newfile-link2.txt /tmp/newfile-symlink.txt
[user@host ~]$ ls -l newfile-link2.txt /tmp/newfile-symlink.txt
-rw-rw-r--. 1 user user 12 Mar 11 19:19 newfile-link2.txt
lrwxrwxrwx. 1 user user 11 Mar 11 20:59 /tmp/newfile-symlink.txt -> /home/user/ newfile-link2.txt
[user@host ~]$ cat /tmp/newfile-symlink.txt
Soft Hello World
在上面的例子中,/tmp/newfile-symlink.txt的长列表的第一个字符是l而不是-,这表明该文件是一个软链接,而不是一个普通文件。(d表示该文件是一个目录。)
当原来的常规文件被删除时,软链接仍然会指向该文件,但目标已经消失了。指向丢失的文件的软链接被称为 "悬空软链接"。
[user@host ~]$ rm -f newfile-link2.txt
[user@host ~]$ ls -l /tmp/newfile-symlink.txt
lrwxrwxrwx. 1 user user 11 Mar 11 20:59 /tmp/newfile-symlink.txt -> /home/user/ newfile-link2.txt
[user@host ~]$ cat /tmp/newfile-symlink.txt
cat: /tmp/newfile-symlink.txt: No such file or directory
前面例子中的软链接的一个副作用是,如果你以后创建一个与被删除的文件同名的新文件(/home/user/newfilelink2.txt),软链接将不再是 "挂着的",而是指向新文件。
硬链接不是这样工作的。如果你删除了一个硬链接,然后用普通工具(而不是ln)创建一个新的同名文件,新文件将不会与旧文件链接。
比较硬链接和软链接的一种方法,或许可以帮助你了解它们的工作原理。
一个硬链接将名称指向存储设备上的数据。
一个软链接将一个名称指向另一个名称,该名称指向存储设备上的数据。
一个软链接可以指向一个目录。然后软链接就像一个目录一样。用cd切换到软链接会使当前的工作目录成为被链接的目录。有些工具可能会跟踪你跟随软链接。例如,默认情况下,cd会使用软链接的名称来更新你当前的工作目录,而不是实际目录的名称。(有一个选项-P,可以用实际目录的名称来更新它。)
在下面的例子中,创建了一个名为/home/user/configfiles的软链接,指向/etc目录。
[user@host ~]$ ln -s /etc /home/user/configfiles
[user@host ~]$ cd /home/user/configfiles
[user@host configfiles]$ pwd
/home/user/configfiles
文件名与shell扩展匹配
目标
完成本节内容后,你能够利用Bash shell的模式匹配功能,有效地运行许多命令。
命令行扩展
Bash shell有多种方式来扩展命令行,包括模式匹配、主目录扩展、字符串扩展和变量替换。其中最强大的可能是路径名匹配功能,历史上被称为 globbing。Bash globbing功能,有时也被称为 "通配符",它使管理大量文件变得更加容易。通过使用 "扩展 "的元字符来匹配文件名和路径名,命令可以一次性对一组集中的文件执行。
模式匹配
Globbing是一个shell命令解析操作,它将通配符模式扩展为匹配的路径名列表。在执行命令之前,命令行的元字符会被匹配列表所取代。不返回匹配的模式会将原始模式请求显示为字面文本。以下是常见的元字符和模式类。
元字符和匹配表
通配符
匹配规则
*
匹配 0 或多个字符
?
匹配任意单个字符
[abc...]
括号内的任何一个字符(方括号之间)。
[!abc...]
任何一个不在括号内的字符(方括号之间)
[^abc...]
任何一个不在括号内的字符(方括号之间)
[[:alpha:]]
任何英文字母字符。
[[:lower:]]
任何小写字母。
[[:upper:]]
任何大写字母。
[[:alnum:]]
任何字母字符或数字。
[[:punct:]]
何非空格或字母数字的可打印字符。
[[:digit:]]
从0到9的任何单个的字母或数字。
[[:space:]]
任何一个空白字符。这可能包括制表符、换行符、回车符、换页符或空格。
在接下来的几个例子中,假设你运行了以下命令来创建一些示例文件。
[user@host ~]$ mkdir glob; cd glob
[user@host glob]$ touch alfa bravo charlie delta echo able baker cast dog easy
[user@host glob]$ ls
able alfa baker bravo cast charlie delta dog easy echo
[user@host glob]$
第一个例子将使用带有星号(*)和问号(?)字符的简单模式匹配,以及一类字符,来匹配其中的一些文件名。
[user@host glob]$ ls a*
able alfa
[user@host glob]$ ls *a*
able alfa baker bravo cast charlie delta easy
[user@host glob]$ ls [ac]*
able alfa cast charlie
[user@host glob]$ ls ????
able alfa cast easy echo
[user@host glob]$ ls ?????
baker bravo delta
[user@host glob]$
波浪号扩展
斜线字符(~),匹配当前用户的主目录。如果它以斜线(/)以外的字符串开始,shell会将该字符串解释为用户名,如果有匹配的,则将该字符串解释为斜线之前的用户名,并以该用户的主目录的绝对路径代替该字符串。如果没有匹配的用户名,那么将使用实际的斜线后面的字符串来代替。
在下面的例子中,echo命令用于显示斜线字符的值。echo命令还可以用来显示括号和变量扩展字符等的值。
[user@host glob]$ ls ~root
/root
[user@host glob]$ ls ~user
/home/user
[user@host glob]$ ls ~/glob
able alfa baker bravo cast charlie delta dog easy echo
[user@host glob]$ echo ~/glob
/home/user/glob
[user@host glob]$
花括号扩展
括号扩展用于生成任意的字符串。括号包含一个逗号分隔的字符串列表,或一个序列表达式。其结果包括括号定义的前面或后面的文本。括号扩展可以嵌套,一个在另一个里面。同样,双点语法(..)扩展为一个序列,这样{m..p}将扩展为m n o p。
[user@host glob]$ echo {Sunday,Monday,Tuesday,Wednesday}.log
Sunday.log Monday.log Tuesday.log Wednesday.log
[user@host glob]$ echo file{1..3}.txt
file1.txt file2.txt file3.txt
[user@host glob]$ echo file{a..c}.txt
filea.txt fileb.txt filec.txt
[user@host glob]$ echo file{a,b}{1,2}.txt
filea1.txt filea2.txt fileb1.txt fileb2.txt
[user@host glob]$ echo file{a{1,2},b,c}.txt
filea1.txt filea2.txt fileb.txt filec.txt
[user@host glob]$
花括号扩展的一个实际用途是快速创建多个文件或目录。
[user@host glob]$ mkdir ../RHEL{6,7,8}
[user@host glob]$ ls ../RHEL*
RHEL6 RHEL7 RHEL8
[user@host glob]$
变量扩展
变量的作用就像一个命名的容器,可以在内存中存储一个值。变量使人们可以很容易地从命令行或shell脚本中访问和修改存储的数据。
你可以使用下面的语法将数据作为值分配给一个变量:
[user@host ~]$ VARIABLENAME=value
你可以在命令行中使用变量扩展来将变量名转换为它的值。如果一个字符串以美元符号($)开头,那么shell将尝试使用该字符串的其余部分作为变量名,并将其替换为变量的任何值。
[user@host ~]$ USERNAME=operator
[user@host ~]$ echo $USERNAME
operator
为了避免由于其他shell扩展所造成的错误,可以把变量的名字放在大括号里,例如${VARIABLENAME}。
[user@host ~]$ USERNAME=operator
[user@host ~]$ echo ${USERNAME}
operator
Shell变量和使用这些变量的方法将在本课程后面更深入地介绍。
命令替换
命令替换允许在命令行中用命令的输出来替换命令本身。当一个命令被包含在括号内,并在其前面加上美元符号(
(command)**形式可以将多个命令的扩展形式相互嵌套在一起。
[user@host glob]$ echo Today is $(date +%A).
Today is Wednesday.
[user@host glob]$ echo The time is $(date +%M) minutes past $(date +%l%p).
The time is 26 minutes past 11AM.
[user@host glob]$
转义扩展
许多字符在Bash shell中都有特殊意义。为了防止shell在命令行的部分内容上执行shell扩展,你可以引用和转义字符和字符串。
backslash (\)是Bash shell中的一个转义字符。它将保护紧随其后的字符不被扩展。
[user@host glob]$ echo The value of $HOME is your home directory.
The value of /home/user is your home directory.
[user@host glob]$ echo The value of \$HOME is your home directory.
The value of $HOME is your home directory.
[user@host glob]$
在上面的例子中,保护美元符号不被扩展,导致Bash把它当成一个正则字符,它没有对$HOME进行变量扩展。
为了保护较长的字符串,可以用单引号(')或双引号(")来包围字符串。它们的效果略有不同。单引号会停止所有shell的扩展。双引号阻止了大部分的shell扩展。
使用双引号来抑制 globbing 和 shell 扩展,但仍然允许命令和变量替换。
[user@host glob]$ myhost=$(hostname -s); echo $myhost
host
[user@host glob]$ echo "***** hostname is ${myhost} *****"
***** hostname is host *****
[user@host glob]$
用单引号对所有文字进行字面解释。
[user@host glob]$ echo "Will variable $myhost evaluate to $(hostname -s)?"
Will variable myhost evaluate to host?
[user@host glob]$ echo 'Will variable $myhost evaluate to $(hostname -s)?'
Will variable $myhost evaluate to $(hostname -s)?
[user@host glob]$
总结
Linux系统中的文件被组织成一个单一的倒置目录树,称为文件系统层次结构。
绝对路径以/开头,指定文件在文件系统层次结构中的位置。
相对路径不以"/"开头,并指定一个文件相对于当前工作目录的位置。
五个关键命令用于管理文件:mkdir、rmdir、cp、mv和rm。
硬链接和软链接是让多个文件名指向同一个数据的不同方式。
Bash shell提供了模式匹配、扩展和替换功能,帮助你高效地运行命令。