第04章:操作文件和目录
本章将学习以下命令
cp
复制文件和目录(Copy files and directories)mv
移动或重命名文件和目录(Move/rename files and directories)mkdir
创建目录(Create directories)rm
移除文件和目录(Remove files and directories)ln
创建硬链接和符号链接(Create hard and symbolic links)
以上五个命令是极其常用的 Linux 命令。它们都可以操作文件和目录两者。
现在,坦白地说,这些命令所执行的任务能够在图形界面中更简单地操作。在文件管理器中,我们能拖放一个文件到另外一个目录,剪切粘贴文件,删除文件等等。那为什么还要使用这些命令行程序呢?
答案是强大且灵活。图形界面能处理简单的文件操作,而命令行程序能更简便地执行复杂任务。例如,我们如何能从一个目录中仅仅复制目标文件夹中所没有的或者比目标文件夹更新的 HTML 文件到另一个文件夹?对于一个文件管理器来说,这个任务超级难,但是用命令行却极其简单:
通配符
在使用命令之前,我们需要讨论一下 shell 中能让这些命令变得更强大的一个特性。由于 shell 使用了如此多的文件名,因此提供了特殊字符来帮助我们便捷地指定一组文件名。这些特殊字符,就是通配符(wildcards)。使用通配符(也被称作 globbing),能让我们基于字符模式(patterns of characters)选择文件名。表 4-1 列出了一些通配符及其效果。
表 4-1:通配符
通配符
意义
*
匹配任意字符
?
匹配任意单个字符
[characters]
匹配组中任意单个字符
[!characters]
匹配不在组中的任意单个字符
[[:class:]]
匹配指定字符组中的任意字符
表 4-2:常用字符组
字符组
意义
[:alnum:]
匹配任意字母数字
[:alpha:]
匹配任意字母
[:digit:]
匹配任意数字
[:lower:]
匹配任意小写字母
[:upper:]
匹配任意大写字母
使用通配符,能构建复杂的文件名选择标准。表 4-3 提供了一些字符模式的样例及其所匹配的文件名。
表 4-3:通配符样例
样式
所匹配
*
所有文件
g*
以 "g" 开头的任意文件
b*.txt
以 "b" 开头的且以 ".txt" 结尾的任意文件
Data???
以 "Data" 开头,且其后跟随三个字符的任意文件
[abc]*
以 "a" 或 "b" 或 "c" 开头的任意文件
BACKUP.[0-9][0-9][0-9]
以 "BACKUP." 开头且跟随三个数字的任意文件
[[:upper:]]
以大写字母开头的任意文件
[![:digit:]]
不以数字开头的任意文件
*[[:lower:]123]
以小写字母或者 "1" "2" "3" 结尾的文件
通配符能用在所有接受以文件名为参数的命令中,我们将在第七章「如 Shell 所见的世界」中详加讨论。
字符序列
如果之前使用过类 Unix 系统或者读过关于这个主题的书,你可能遇到过 [A-Z] 和 [a-z] 这样的字符序列符号。这些传统的 Unix 符号在老版本的 Linux 中也一样正常工作。它们还能工作,但是你要小心它们不会产生你所希望的结果,除非你做了正确的配置。当前情况下,应该避免使用它们,而代之以表 4-2 所列的字符组。
在图形界面中的通配符
通配符的特殊用途,不仅在于它能在命令行中频繁使用,而且在一些图形文件管理器中也得到支持。
在 Nautilus(GNOME 的文件管理器),你能使用「编辑/选择样式」菜单项来选择文件。仅输入一个文件选择样式,当前目录中符合条件的文件会高亮以供选择。
某些版本的 Dolphin 和 Konqueror(KDE 的文件管理器),能在地址栏中直接输入通配符。例如,你想看所有以 "u" 开头的在
/usr/bin
目录中的文件,在地址栏中输入/usr/bin/u*
即可。许多基于命令行的理念也进入到图形界面。这使得 Linux 桌面更加强大。
mkdir - 创建目录
mkdir
命令用来创建目录,用法如下:
关于符号的注释:当三个句点跟随一个参数的时候,如上例所示,意味着这个参数可以被重复,因此下面的命令:
将创建一个名为 dir1
的目录。若如下:
将创建三个目录,分别是 dir1
、dir2
、dir3
。
cp - 复制文件和目录
cp
命令复制文件或目录。有两种不同的方法。其一:
复制单个文件或目录 item1
到文件或目录 item2
。其二:
复制多个项目(不论是文件或目录)到一个目录。
有用的选项及其范例
表 4-4 列出了 cp
的最常用的选项。
表 4-4 cp
选项
选项
长选项
意义
-a
--archive
复制文件及目录,以及其全部属性,包含属主和权限。通常,所复制的副本采用执行复制命令的用户的默认属性。我们将在第九章「权限」中了解文件权限。
-i
--interactive
覆盖已存在的文件前,会提示用户确认。若无此选项,cp
会静默地(即没有任何提示地)覆盖文件。
-r
--recursive
递归复制目录及目录中的内容。在复制目录时需要该选项(或 -a
选项)。
-u
--update
从一个目录复制文件到另一个目录时,仅复制那些比目标目录中更新的和于不存在目标目录的文件。这在复制大量文件时很有用,可以忽略那些不需要复制的文件。
-v
--verbose
执行复制命令时,显示详细信息。
表 4-5 cp
举例
命令
结果
cp file1 file2
复制 file1
到 file2
,如果 file2
已存在,将用 file1
的内容覆盖 file2
。如果 file2 不存在,则直接创建该文件。
cp -i file1 file2
作用如上条命令。区别在于当 file2 存在时,会提示用户是否覆盖该文件。
cp file1 file2 dir1
复制 file1 和 file2 到 dir1,前提是 dir1 必须已经存在。
cp dir1/* dir2
使用通配符复制 dir1 中的所有文件到 dir2。前提是 dir2 必须已经存在。
cp -r dir1 dir2
复制目录 dir1 中的内容到目录 dir2。如果 dir2 不存在,则先创建该目录。复制完成后,两个目录中的内容完全相同。 若 dir2 已经存在,复制 dir1 及其内容到 dir2 中。
mv - 移动、重命名文件
mv
命令执行移动文件和重命名文件两个任务,依赖于如何使用。在任何情况下,命令执行后,原始文件都不再存在了。mv
用起来跟 cp
命令差不多:
以上命令移动或重命名文件或目录 item1
到 item2
。或如:
移动一个或多个项目到另一个目录中。
有用的选项及其范例
mv
和 cp
共享很多相同的选项,如表 4-6。
表 4-6 mv
选项
选项
长选项
意义
-i
--interactive
覆盖已存在的文件前,会提示用户确认。若无此选项,mv
会静默地(即没有任何提示地)覆盖文件。
-u
--update
从一个目录移动文件到另一个目录时,仅移动那些比目标目录中更新的和于不存在目标目录的文件。这在移动大量文件时很有用,可以忽略那些不需要移动的文件。
-v
--verbose
执行移动命令时,显示详细信息。
表 4-7 列出了 mv
命令的一些用法示例。
表 4-7 mv
示例
命令
结果
mv file1 file2
移动 file1
到 file2
,如果 file2
已存在,将用 file1
的内容覆盖 file2
。如果 file2 不存在,则直接创建该文件。上述任何情况下,file1 都不复存在。
mv -i file1 file2
作用如上条命令。区别在于当 file2 存在时,会提示用户是否覆盖该文件。
mv file1 file2 dir1
移动 file1 和 file2 到 dir1,前提是 dir1 必须已经存在。
mv dir1 dir2
如果 dir2 不存在,则先创建该目录,而后移动 dir1
中的内容到 dir2
中,并删掉 dir1
目录。
若 dir2 已经存在,移动 dir1 及其内容到 dir2 中。
rm - 移除文件和目录
rm
命令用来移除(删除)文件和目录,用法如下:
item
是一个或多个文件和目录。
有用的选项和示例
表 4-8 描述了一些 rm
常用的选项。
表 4-8:rm
选项
选项
长选项
意义
-i
--interactive
删除已存在的文件前,会提示用户确认。若无此选项,rm
会静默地(即没有任何提示地)删除文件。
-r
--recursive
递归删除目录。意味着被删除的目录中如果有子目录,也会被一并删除。在删除目录时需要该选项。
-f
--force
忽略不存在的文件,并且不给出提示。 此选项会覆盖 --interactive
选项。
-v
--verbose
执行删除命令时,显示详细信息。
表 4-9 提供了一些 rm
的示例。
表 4-9 rm
示例
命令
结果
rm file1
静默删除 file1。
rm -i file1
作用如上条命令,区别在于删除前会给出提示。
rm -r file1 dir1
删除 file1 和 dir1 中的内容。
rm -rf file1 dir1
作用如上条命令,区别在于如果 file1 或 dir1 不存在,rm
命令也会继续静默执行。
谨慎使用 rm!
Linux 和类 Unix 系统没有撤销删除的命令。一旦用
rm
命令删除了的文件,就不复存在了。Linux 假设你是聪明的,你知道你在干什么。特别需要小心的是通配符。考虑这个经典示例。你打算删掉一个目录中所有的 HTML 文件,于是你输入如下命令:
这是正确的,但如果意外的在
*
和.html
之间加了个空格:
rm
命令就会删除目录中所有的文件,然后反馈给你说「并没有一个叫.html
的文件。有用的技巧:无论何时,当你使用带通配符的
rm
(同时注意你所键入的字符),请先用ls
测试一下。这会让你看到哪些文件会被删除。然后用向上箭头键调用上次命令,把ls
替换为rm
。
ln - 创建链接
ln
用来创建硬链接或符号链接。它有下面两种用法。其一创建硬链接:
其二,创建符号链接:
上述 item
可以是文件或目录。
硬链接
相较于更现代的符号链接,硬链接是 Unix 原生的创建链接的方式。默认情况下,每个文件都有一个硬链接,为文件命名。当我们创建一个硬链接,我们就为一个文件创建了一个附加的目录条目。硬链接有两个重要的限制:
一个硬链接不能指向其文件系统之外的文件。意味着一个链接不能指向不在同一磁盘分区中的文件。
硬链接不能指向目录。
硬链接与文件本身无法区分。与符号链接不同,当我们列出一个含有硬链接的目录内容的时候,我们看不到关于链接的特别指示。当删除一个硬链接时,链接被移除,但其文件本身却继续存在(即其空间没有被重新分配),直到该文件所有的链接都被删除。
这对于理解硬链接非常重要,因为你可能随时会遇到他们。不过现代操作更倾向于使用符号链接,我们随后讨论。
符号链接
符号链接是用来克服硬链接的限制的。符号链接创建一个特别的文件类型,包含一个文本指针,指向文件或目录。从这方面考虑,有点类似 Windows 的快捷方式,当然它们比 Windows 早了很多年。
被符号链接指向的文件,和符号链接自身,很大程度上无法区分彼此。例如,如果我们对符号链接写了些东西,也就写到了被指向的文件。当我们删掉符号链接,那仅仅是链接被删除了,文件本身没有被删除。如果文件在符号链接之前被删除,符号将继续存在,但是不指向任何文件。这种情况,称为链接被断开(broken)。在很多情况下,ls
命令用一种可区分的颜色(如红色)显示已断开的链接,以展示其存在。
链接的概念看起来很令人困惑,但是且放一边。我们打算尝试一下这些东西,希望能变得清晰一些。
建一个游乐场
因为我们打算做一些真实的文件操作,所以让我们先建造一个安全的所在去「玩」文件操作命令。首先我们需要在家目录中建一个工作用的目录,名叫 playground
。
创建目录
mkdir
用来创建目录。创建目录前,我们要确认是在自己的家目录中,然后再创建一个新目录。
为了让游乐场更有趣,要在目录内新建两个目录 dir1
和 dir2
。我们先切换当前目录到 playground
,然后再执行一次 mkdir
。
注意 mkdir
允许接受多个参数,能让我们在一个命令内创建两个目录。
复制文件
下一步,让我们放些数据在游乐场中。我们可以用 cp
复制文件进文件夹,来复制一个 /etc
目录中的 passwd
文件。
请留意一下我们用一个句点(.
)来指代我们当前工作目录。我们可以用 ls
来看一下目录中的文件。
现在,仅仅为了好玩,加个选项 -v
来看下:
cp
命令再次执行,但是这次显示了一条简短的信息,指示正在执行的是什么操作。注意 cp
命令在覆盖上一次复制的文件时没有给出任何警告。重申一下,这是因为 cp
命令假定我们知道自己正在做什么。我们可以加入 -i
选项。
此时在提示符处回复 y
将会导致文件被覆盖,其它任意字符(例如 n
)都会导致 cp
命令保留现有的文件。
移动和重命名文件
现在,passwd
这个文件名看起来不好玩,来给它改个名:
让我们把这个重命名的文件挪到每个目录里转一圈,然后再挪回来。
现在来看一下移动目录的效果。首先,再次把数据文件移动到 dir1
中:
然后把 dir1
移动到 dir2
中,并用 ls
命令确认一下:
注意,因为 dir2
已经存在,所以 mv
命令会将 dir1
移动到 dir2
中,否则的话,将重命名 dir1
为 dir2
。最后,让我们把文件夹和文件放回原来的地方。
创建硬链接
现在我们尝试一些链接。我们先创建一些硬链接:
现在,对于文件 fun
,我们有四个实例。来看一下目录:
我们注意到, fun
和 fun-hard
的第二个字段中包含的是 4
,是对于一个文件的硬链接的编号。记住,一个文件总是存在至少一个硬链接,因为文件名本身就是由链接创建的。所以我们如何知道 fun
和 fun-hard
在事实上是同一个文件?ls
命令对此不是很有帮助,我们看到这两个文件具有相同的文件大小(第五个字段),单凭这一点,也还是不能确认的。要解决这个问题,我们不得不更深入探讨一下。
当考虑硬链接时,把文件想象成两个组成部分,会很有帮助:
数据部分,包含文件内容。
名称部分,包含文件名称。
当我们创建了硬链接,我们实际上创建了一个指向同一个数据部分的附加的名称部分。系统分配一个磁盘区块的串给一个索引节点(inode),以关联名称部分。因此,每个硬链接指向一个包含特定文件内容的索引节点。
ls
命令可以调用 -i
选项来揭示这个信息。
在这个版本的列表中,首字段是索引节点编号,我们能看到 fun
和 fun-hard
具有同一索引节点编号,即可确认两者为同一文件。
创建符号链接
为了克服硬链接的以下两个短处,我们创建了符号链接:
硬链接不能跨物理设备。
硬链接不能指向目录,仅能指向文件。
符号链接是一种特殊的文件,包含指向目标文件或目录的文本指针。创建符号链接的方法类似于创建硬链接。
第一个例子非常简单明了,我们加了一个 -s
选项来创建一个符号链接,而不是硬链接。但是下面两个是什么?记住,当我们创建了一个符号链接,我们创建了一个与目标文件关联的文本描述。如果用 ls
,能更方便地看到:
dir1
中的 fun-sym
的第一个字段中的 l
显示其为一个符号链接,指向 ../fun
,并且是正确的。相对于 fun-sym
,fun
处在其上级目录中。同时注意到,符号链接文件的长度是 6
,是 ../fun
这串字符的长度,而非该符号链接所指向的文件的长度。
在创建符号链接时,我们也可以使用绝对路径名,如下:
或者如前例所示用相对路径名。大多数情况下,使用相对路径名更合适,因为这样就不会因为移动或重命名符号链接所在的目录和所指向的文件所在的目录,而导致链接失效。
除了常规文件,符号链接还能指向目录。
移除文件和目录
如前所述,rm
命令用来删除文件和目录。我们准备用它来清理一下游乐场。首先删掉一个硬链接。
工作得一如预期。fun-hard
文件消失了,如第二个字段所示,fun
文件的链接计数从 4 减少到了 3。接下来我们删除文件 fun
,为了有趣点,我们加了个 -i
的选项来显示它如何工作的。
键入 y
以删除文件。现在来看一下 ls
的输出,注意到 fun-sym
发生了什么了?一旦符号链接指向一个现时不存在的文件,链接就破损了。
大多数 Linux 发行版会配置 ls
显示破损的链接。破损链接的存在对其自身而言不存在危险,但会显得相当混乱。如果我们尝试使用一个破损的链接:
让我们清理一下,删除符号链接:
关于符号链接要记住的一件事,大多数文件操作都是在链接的目标上执行的,而不是链接本身。rm
命令是个例外当我们删除一个链接,就是删掉链接本身,而非链接的目标。
最后,我们删掉我们的游乐场。我们要回到家目录,用 rm
加递归选项 -r
删掉 playground
及其所包含的全部文件和子目录。
在图形界面创建符号链接
GNOME 和 KDE 所提供的文件管理器,提供了一个简单且自动的方法来创建符号链接。在 GNOME,按住 Ctrl+Shift,然后拖动一个文件,就创建了一个链接,而非复制(或移动)该文件。在 KDE,当一个文件被拖动时,会显示一个小菜单以供选择是复制还是移动,或是创建一个链接。
总结
本章我们学习了不少内容,需要一段时间来消化。要一遍遍做游乐场练习来熟悉。对基本文件操作命令及通配符有个好的理解,是很重要的。在练习时,可以自由发挥,多加入一些文件和目录,使用通配符来指定多个文件,以便执行各种操作。刚开始,链接的概念会令人困扰,花些时间来学习它们是如何工作的。它们会成为真正的救生员。
扩展阅读
Last updated
Was this helpful?