第四章 操作文件与目录

前言

  1. 本章将介绍如下命令:
  • cp: 复制文件和目录
  • mv: 移动或重命名文件和目录
  • mkdir: 创建目录
  • rm: 移除文件和目录
  • ln: 创建硬链接和符号连接
  1. 以上 5 个命令属于最常使用 Linux 命令之列,可用来操作文件与目录。
  2. 坦率地说,使用图形文件管理器来执行一些由这些命令执行的任务要容易多。使用文件管理器,我们可以将文件从一个目录拖放到另一个目录,我们可以剪切和粘贴文件,我们可以删除文件。
  3. 使用命令行程序的原因是其具有强大的功能和灵活的操作。
  4. 虽然使用图形文件管理器能轻松实现简单的文件操作,但是对于复杂的任务,使用命令行程序更容易完成。
  5. 例如,将所有 HTML 文件从一个目录复制到目标目录,要完成这个任务,使用文件管理器则相当困难,而使用命令行则很容易。
    1
    cp -u *.html destination

通配符

  1. 基本介绍
  • 在开始使用命令之前,我们需要介绍一个使命令行如此强大的 shell 特性
  • 由于 shell 需要经常使用文件名,因此它提供了一些特殊字符来帮助你快速指定一组文件名,这些特殊字符称为通配符
  • 通配符 (也叫文件名替换) 允许用户依据字符模式选择文件名
  • 通配符的使用使得为文件名构建复杂的筛选标准成为可能
  1. 通配符以及它们所选择的对象
通配符 匹配项
* 匹配任意多个字符(包括 0 个和 1 个)
? 匹配任意单个字符(不包括 0 个)
[characters] 匹配任意一个属于字符集中的字符
[!characters] 匹配任意一个不属于字符集中的字符
[[:class:]] 匹配任意一个属于指定字符类中的字符
  1. 通配符的字符类
字符类 匹配项
[:alnum:] 匹配任意一个字符或数字
[:alpha:] 匹配任意一个字母
[:digit:] 匹配任意一个数字
[:lower:] 匹配任意一个小写字母
[:upper:] 匹配任意一个大写字母
  1. 通配符模式及其匹配内容
形式 匹配项
g* 以 g 开头的任一文件
b*.txt 以 b 开头,中间有任意多个字符,并以 .txt 结尾的任一文件
Data??? 以 Data 开头,后面跟三个字符的任一文件
[abc]* 以 abc 中任一开头的任一文件
BACKUP.[0-9][0-9][0-9] 以 BACKUP. 开头,后面紧跟 3 个数字的任一文件
[[:upper:]]* 以大学字母开头的任一文件
[![:digit:]] 不以数字开头的任一文件
*[[:lower:123]] 以小写字母或数字 1、2、3 中的任一结尾的文件

mkdir - 创建目录

  1. mkdir 基本介绍
  • mkdir 命令是是用来创建目录的,格式如下:
    1
    mkdir directory...
  • 创建单个 dir1 目录,输入:
    1
    mkdir dir1
  • 输入以下命令可以创建 3 个目录:
    1
    mkdir dir1 dir2 dir3

cp - 复制文件和目录

  1. cp 基本介绍
  • cp 文件用来复制文件和目录,它有两种不同的使用方式。
  • 将单个文件或目录 item1 复制到文件或目录 item2 中。
    1
    cp item1 item2
  • 将多个项目(文件或目录)复制进一个目录中。
    1
    cp item... directory
  1. cp 命令选项
选项 含义
-a, --archive 复制文件和目录及其属性,包括所有权和权限。通常来说,复制的文件具有用户所操作文件的默认属性
-i, --interactive 在覆盖一个已存在的文件前,提示用户进行确认。如果没有指定该选项,cp 会默认覆盖文件
-r, --recursive 递归地复制目录及其内容。复制目录时需要这个选项 (或 -a 选项)
-u, --update 当将文件从一个目录复制到另一个目录时,只会复制那些目标目录中不存在的文件或是目标目录相应文件的更新文件
-v, --verbose 复制文件时,显示信息性消息 (informative message)
  1. 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 目录相同的内容

mv - 移除和重命名文件

  1. mv 基本介绍
  • mv 命令可以执行文件移动和文件重命名操作,这具体取决于如何使用它。在这两种情况下,完成操作之后,原来的文件名将不存在
  • mv 的使用方法与 cp 基本相似。将文件 (或目录) item1 移动 (或重命名) 为 item2
    1
    mv item1 item2
  • 将一个或多个条目从一个目录移动到另一个目录下
    1
    mv item... directory
  1. mv 选项
选项 含义
-i, --interactive 覆盖一个已存在的文件之前,提示用户确认。如果没有指定该选项,mv 会默认覆盖文件
-u, --update 将文件从一个目录移动到另一个目录,只移动那些目标目录中不存在的文件或是目标目录里相应文件的更新文件
-v, --verbose 移动文件时显示信息性消息
  • 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 将目录 dir1 (和其他内容) 移到目录 dir2 下。如果目录 dir2 不存在,创建目录 dir2 ,将目录 dir1 的内容移到 dir2 下,同时删除目录 dir1

rm - 删除文件和目录

  1. rm 基本介绍
  • rm 命令用来移除 (删除文件) 和目录,如下所示。
    1
    rm item ...
  • 其中 item 是一个或多个文件 (或目录) 的名称。
  1. rm 常用选项
选项 含义
-i, --interactive 删除一个已经存在的文件前,提示用户确认。如果没有指定这个选项,rm 命令会默认删除文件
-r, --recursive 递归地删除目录。也就是说,如果删除的目录有子目录的话,也要将其删除。要删除一个目录,则必须指定该选项
-f, --force 忽略不存在的文件并无需提示确认。该选项会覆盖 --interactive
-v, --verbose 删除文件时显示信息性消息
  1. rm 常用实例
命令 结果
rm file1 在不提示用户的情况下,删除 file1
rm -i file1 删除 file1 前,提示用户确认
rm -r file1 dir1 删除 file1、dir1 以及它们的内容
rm -rf file1 dir1 同上,当在 file1 或 dir1 不存在时,rm 仍会继续执行,且不提示用户

ln - 创建链接

  1. ln 概述
  • ln 命令可用来创建硬链接或是符号链接。它的使用方式有两种:
    1
    2
    3
    4
    # 创建硬链接
    ln file link
    # 创建符号链接
    ln -s item link # 这里的 item 可以是文件也可以是目录。
  1. 硬链接
  • 硬链接是最初 UNIX 用来创建链接的方式,符号链接较之更为先进。
  • 默认情况下,每个文件有一个硬链接,该硬链接会给文件起名字。当创建一个硬链接的时候,也为这个文件创建了一个额外的目录条目。
  • 硬链接有两条重要的局限性:
    • 硬链接不能引用自身文件系统之外的文件
    • 硬链接无法引用目录
  • 硬链接和文件本身没有什么区别。与包含符号链接的目录列表不同,包含硬链接的目录列表没有特别的链接指示说明。
  • 当硬链接被删除时,只是删除了这个链接,但是文件本身的内容依然存在 (也就是说,该空间没有释放) ,除非该文件的所有链接都被删除了。
  1. 符号链接
  • 符号链接是为了克服硬链接的局限性而创建的。
  • 符号链接是通过创建一个特殊类型的文件来起作用的,该文件包含了指向引用文件或目录的文本指针
  • 符号链接指向的文件与符号链接自身几乎没有区别
  • 当删除一个符号链接时,删除的只是符号链接而没有删除文件本身
  • 如果先于符号链接之前删除文件,那么这个链接依然存在,但却不指向任何文件。此时这个链接称为坏链接

实战演练

  1. 概述
  • 由于我们要做一些实际的文件操作,我们先来创建一个安全的地带,来执行文件操作命令
  • 首先,我们需要一个工作目录。我们在主目录里创建一个目录并命名为 playground
  1. 创建目录
  • mkdir 命令用来创建一个目录。为了创建 playground 目录,我们首先要保证当前目录是主目录,然后再创建新目录
    1
    2
    [me@linuxbox ~]$ cd
    [me@linuxbox ~]$ mkdir playground
  • 在 playground 目录中新建两个目录,命名为 dir1 、 dir2
  • 切换工作目录为 playground ,然后再次执行 mkdir 命令
    1
    2
    [me@linuxbox ~]$ cd playground
    [me@linuxbox playground]$ mkdir dir1 dir2
  • 需要注意的是, mkdir 命令可以接受多个参数,从而允许我们用一个命令创建两个目录
  1. 复制文件
  • 接下来,让我们在创建的目录中放入一些数据,这一过程可以通过文件复制来完成
  • 通过使用 cp 命令,我们可以将 /etc 目录中的 passwd 文件复制到当前工作目录里
    1
    [me@linuxbox playground]$ cp /etc/passwd .
  • 如果我们此时执行 ls 命令,将会看到我们的文件
    1
    2
    3
    4
    5
    [me@linuxbox playground]$ ls -l
    total 12
    drwxrwxr-x 2 me me 4096 2012-01-10 16:40 dir1
    drwxrwxr-x 2 me me 4096 2012-01-10 16:40 dir2
    -rw-r--r-- 1 me me 1650 2012-01-10 16:07 passwd
  • 现在让我们使用 -v 选项,重复操作复制命令,来看看结果如何
    1
    2
    [me@linuxbox playground]$ cp -v /etc/passwd .
    '/etc/passwd' -> '.passwd'
  • cp 命令再次执行复制操作,但是,这一次显示了一条简洁的信息来指明它正在执行什么操作。
  • 需要注意的是,在没有任何警告的情况下,cp 命令覆盖了第一次的复制内容。
  • cp 命令会假定用户清楚自己当前的操作,加上 -i 选项可以获得警告信息。
    1
    2
    [me@linuxbox playground]$ cp -i /etc/passwd .
    cp: overwrite './passwd'?
  • 通过在提示符下输入 y ,文件就会被重写;任何其他的字符会使 cp 命令保留该文件。
  1. 移动和重命名文件
  • 现在,passwd 这个名字似乎没有那么有趣,而我们毕竟是在进行实战演练,因此我们给它改个名字。
    1
    [me@linuxbox playground]$ mv passwd fun
  • 现在传送 fun 文件,这是通过将重命名的文件移动到各个目录,然后再移动回当前目录来实现的。
    • 首先移到目录 dir1 下,然后:
      1
      [me@linuxbox playground]$ mv fun dir1
    • 将文件从目录 dir1 移到 dir2 ,然后:
      1
      [me@linuxbox playground]$ mv dir1/fun dir2
    • 再将文件 fun 重新移到当前工作目录下
      1
      [me@linuxbox playground]$ mv dir2/fun .
  • 下面来看 mv 命令的效果。首先,再次将数据文件移到目录 dir1
    1
    [me@linuxbox playground]$ mv fun dir1
  • 然后将目录 dir1 移到 dir2 并且使用 ls 命令确认
    1
    2
    3
    4
    5
    6
    7
    [me@linuxbox playground]$ mv dir1 dir2
    [me@linuxbox playground]$ ls -l dir2
    total 4
    drwxrwxr-x 2 me me 4096 2012-01-11 06:06 dir1
    [me@linuxbox playground]$ ls -l dir2/dir1
    total 4
    -rw-r--r-- 1 me me 1650 2012-01-10 16:33 fun
  • 注意,因为目录 dir2 已经存在,mv 命令将目录 dir1 移到 dir2
  • 如果 dir2 不存在,mv 将 dir1 重命名为 dir2 。最后,我们将所有东西放回原处
    1
    2
    [me@linuxbox playground]$ mv dir2/dir1 .
    [me@linuxbox playground]$ mv dir1/fun .
  1. 创建硬链接
  • 现在,我们试着创建一些链接。首先是创建硬链接,我们先按照如下方式创建一些指向数据文件的链接:

    1
    2
    3
    [me@linuxbox playground]$ ln fun fun-hard
    [me@linuxbox playground]$ ln fun dir1/fun-hard
    [me@linuxbox playground]$ ln fun dir2/fun-hard
  • 目前有 4 个文件 fun 的实例。来看一下 playground 目录

    1
    2
    3
    4
    5
    6
    [me@linuxbox playground]$ ls -l
    total 16
    drwxrwxr-x 2 me me 4096 2012-01-14 16:17 dir1
    drwxrwxr-x 2 me me 4096 2012-01-14 16:17 dir2
    -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun
    -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun-hard
  • 可以注意到,在列表中,文件 fun 和 fun-hard 的第二个字段都是 4 ,这是文件 fun 存在的硬链接数目

  • 由于文件名是由链接创建的,所以一个文件通常至少有一个链接。

  • 提到硬链接时,可以想象文件是由两部分组成的,即包含文件内容的数据部分和包含文件名的名称部分。创建硬链接时,实际上是创建了额外的名称,这些名称都指向同一数据部分

  • 系统分配了一系列的盘块给所谓的索引节点 (inode) ,该节点随后与文件名称部分建立关联。因此,每个硬链接都指向包含文件内容的具体索引节点

  • ls 命令有一种显示上述信息的方法。它是通过在命令中加上 -i 选项来实现的

    1
    2
    3
    4
    5
    6
    [me@linuxbox playground]$ ls -li
    total 16
    12353539 drwxrwxr-x 2 me me 4096 2012-01-14 16:17 dir1
    12353540 drwxrwxr-x 2 me me 4096 2012-01-14 16:17 dir2
    12353538 -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun
    12353538 -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun-hard
  • 在上面列表中,第一个字段就是索引节点号,可以看到,fun 和 fun-hard 共享同一个索引节点号,这就证实它们是相同的文件。

  1. 创建符号链接
  • 之所以创建符号链接,是为了克服硬链接的两大不足,即硬链接无法跨越物理设备,也无法引用目录,只能引用文件
  • 符号链接是一种特殊类型的文件,它包含了指向目标文件或目录的文本指针
  • 创建符号链接与创建硬链接相似,如下所示
    1
    2
    3
    [me@linuxbox playground]$ ln -s fun fun-sym
    [me@linuxbox playground]$ ln -s ../fun dir1/fun-sym
    [me@linuxbox playground]$ ln -s ../fun dir2/fun-sym
  • 创建符号链接时,同时也创建一个文本来描述目标文件与符号链接有关联
    1
    2
    3
    4
    [me@linuxbox playground]$ ls -l dir1
    total 4
    -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun-hard
    lrwxrwxrwx 1 me me 6 2012-01-15 15:17 fun-sym -> ../fun
  • 在目录 dir1 中, fun-sym 的列表显示它是一个符号链接,这是通过第 1 个字段中的首字符 1 来确认的,并且它也指 ../fun ,这也是正确的
  • 相对于 fun-sym 的实际位置,文件 fun 在它的上一级目录。还要注意到,符号链接文件的长度是 6 ,这是 ../fun 字符串中字符的数字,而不是它所指向的文件的长度
  • 创建符号链接时,可以使用绝对路径名,如下所示:
    1
    [me@linuxbox playground]$ ln -s /home/me/playground/fun dir1/fun-sym
  • 也可以使用相对路径,如前面示例所示
  • 因为相对路径允许包含符号链接的目录被重命名/或移动,而且不会破坏链接,因此会更可取一些
  • 除了普通文件之外,符号链接也可以引用目录
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [me@linuxbox playground]$ ln -s dir1 dir1-sym
    [me@linuxbox playground]$ ls -l
    total 16
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir1
    lrwxrwxrwx 1 me me 4 2012-01-16 14:45 dir1-sym -> dir1
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir2
    -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun
    -rw-r--r-- 4 me me 1650 2012-01-10 16:33 fun-hard
    lrwxrwxrwx 1 me me 3 2012-01-15 15:15 fun-sym -> fun
  1. 移除文件和目录
  • 前面讲到,使用 rm 命令可以删除文件和目录。那么我们就用它来清空 playground 目录
  • 首先,我们删除目录中的一个硬链接
    1
    2
    3
    4
    5
    6
    7
    8
    [me@linuxbox playground]$ rm fun-hard
    [me@linuxbox playground]$ ls -l
    total 12
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir1
    lrwxrwxrwx 1 me me 4 2012-01-16 14:45 dir1-sym -> dir1
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir2
    -rw-r--r-- 3 me me 1650 2012-01-10 16:33 fun
    lrwxrwxrwx 1 me me 3 2012-01-15 15:15 fun-sym -> fun
  • 文件 file-hard 被删除了,文件 fun 的连接数相应的也由 4 变成了 3
  • 接下来,我们删除文件 fun ,我们还会加上 -i 选项,看看执行了哪些操作
    1
    2
    [me@linuxbox playground]$ rm -i fun
    rm: remove regular file 'fun'?
  • 在提示符下输入字符 y ,文件就被删除了。现在看一下 ls 命令的输出
    1
    2
    3
    4
    5
    6
    [me@linuxbox playground]$ ls -l
    total 8
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir1
    lrwxrwxrwx 1 me me 4 2012-01-16 14:45 dir1-sym -> dir1
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir2
    lrwxrwxrwx 1 me me 3 2012-01-15 15:15 fun-sym -> fun
  • 由于 fun-sym -> fun 是一个符号链接,且指向的文件现在已经不存在,所以链接也就被破坏了。
  • 如果试图调用破坏的链接,将会看到如下情况:
    1
    2
    [me@linuxbox playground]$ less fun-sym
    fun-sym: No such file or directory
  • 稍微清理一下,删除符号链接
    1
    2
    3
    4
    [me@linuxbox playground]$ rm fun-sym dir1-sym
    [me@linuxbox playground]$ ls -l
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir1
    drwxrwxr-x 2 me me 4096 2012-01-15 15:17 dir2
  • 有关于符号链接,需要记住一点,即大部分文件操作是以链接目标为对象的,而非链接本身
  • 而 rm 命令是个例外。当删除一个链接的时候,链接本身被删除,但是目标文件依旧存在
  • 最后,我们需要删除目录 playground 。为此,我们将返回主目录,使用 rm 命令的递归选项 (-r) 来删除 playground 目录以及包括子目录在内的所有内容
    1
    2
    [me@linuxbox playground]$ cd
    [me@linuxbox ~]$ rm -r playground

参考文章

  • 转载:Linux 命令行大全