# 文件与目录管理

# 文件与木的检视 ls

ls [-aAdfFhilnrRSt] 文件名或目录名称Â
ls [--color={never,auto,always}] 文件名或目录名称
ls [--full-time] 文件名或目录名称
1
2
3

选项与参数:

  • a:全部的文件,连同隐藏文件(开头为 .)一起列出来(常用)

  • A:全部的文件,连同隐藏文件(不包括 . 和 .. 这两个目录)

  • d:仅列出目录本身,而不是列出目录内的文件数据(常用)

  • f:直接列出结果,而不进行排序(ls 默认以文档名排序)

  • F:根据文件、目录等信息,给予附加数据结构

    如:

    • * 代表可执行文件,
    • / 代表目录
    • = 代表 socket 文件
    • | 代表 FIFO 文件
    # 如这样,会在文件名后面显示符号
    [mrcode@study ~]$ ls -F
    下载/  公共/  图片/  文档/  桌面/  模板/  视频/  音乐/
    
    1
    2
    3
  • h:将文件容量以人类较易读的方式(例如 GB、KB)列出来

  • i:列出 inode 号码,inode 的意义后续讲解

  • l:长数据串输出,包含文件的属性与权限等数据(常用)

  • n:列出 UID 与 GID 而非使用者与群组的名称(UID 与 GID 会在账户管理中讲解)

  • r:将排序结果反向输出,例如原本文件名由小到大,反向则由大到小

  • R:连同子目录内容一起列出来,等于该目录下的所有文件都会显示出来

  • S:按文件容量大小排序

  • t:按时间排序

  • color 颜色配置

    • never:不要依据文件特性给予颜色显示
    • always:显示颜色
    • auto:让系统自行依据设置来判断是否给予颜色
  • full-time:以完整时间模式)包含年月日时分输出

  • time={atime,ctime}:输出 access 时间或改变权限属性时间(ctime),而非内容变更时间

在 linux 中 ls 指令可能是 最常用的,由于文件所记录的信息实在是太多了, 所以默认显示的只有:非隐藏文档、以文件名进行排序、文件名代表的颜色显示

实践练习

# 将家目录下的所有问价列出来,包含属性与隐藏文件
[mrcode@study ~]$ ls -al ~
total 40
drwx------. 18 mrcode mrcode 4096 Oct  8 23:15 .   # 深蓝色
drwxr-xr-x.  4 root   root     42 Oct  8 23:01 ..  # 深蓝色
-rw-------.  1 mrcode mrcode 2927 Oct 11 05:16 .bash_history
-rw-r--r--.  1 mrcode mrcode   18 Aug  8 20:06 .bash_logout
-rw-r--r--.  1 mrcode mrcode  193 Aug  8 20:06 .bash_profile
-rw-r--r--.  1 mrcode mrcode  231 Aug  8 20:06 .bashrc
drwx------. 16 mrcode mrcode 4096 Oct  4 21:33 .cache # 深蓝色

# 接上题,不显示颜色,但在文件名末尾显示该文件名代表的类型
# 实际的终端中看,颜色就没显示了
[mrcode@study ~]$ ls -alF --color=never ~
total 40
drwx------. 18 mrcode mrcode 4096 Oct  8 23:15 ./
drwxr-xr-x.  4 root   root     42 Oct  8 23:01 ../
-rw-------.  1 mrcode mrcode 2927 Oct 11 05:16 .bash_history
-rw-r--r--.  1 mrcode mrcode   18 Aug  8 20:06 .bash_logout
-rw-r--r--.  1 mrcode mrcode  193 Aug  8 20:06 .bash_profile
-rw-r--r--.  1 mrcode mrcode  231 Aug  8 20:06 .bashrc
drwx------. 16 mrcode mrcode 4096 Oct  4 21:33 .cache/

# 显示完整的修改实践(modification time)
[mrcode@study ~]$ ls -al --full-time ~
total 40
drwx------. 18 mrcode mrcode 4096 2019-10-08 23:15:44.109000000 +0800 .
drwxr-xr-x.  4 root   root     42 2019-10-08 23:01:04.516000000 +0800 ..
-rw-------.  1 mrcode mrcode 2927 2019-10-11 05:16:27.662000000 +0800 .bash_history
-rw-r--r--.  1 mrcode mrcode   18 2019-08-08 20:06:55.000000000 +0800 .bash_logout
-rw-r--r--.  1 mrcode mrcode  193 2019-08-08 20:06:55.000000000 +0800 .bash_profile
-rw-r--r--.  1 mrcode mrcode  231 2019-08-08 20:06:55.000000000 +0800 .bashrc
drwx------. 16 mrcode mrcode 4096 2019-10-04 21:33:12.075000000 +0800 .cache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

可以看到 ls 支持的功能很多,这些都是因为 linux 文件系统记录了很多有用的信息的缘故, 那么这些与权限、属性有关的数据放在 i-node 里面的。后续会深入讲解 i-node 的

另外,由于 ls -l 使用频率很高,为此,很多 distribution 在预设情况中已经将 ll 设定为 ls -l 的意思了。

# 复制、删除与移动:cp、rm、mv

  • cp:copy 复制文件,该指令还有其他功能,如建立连接档、比较亮文件的新旧而给予更新,复制整个目录等功能
  • mv:move 移动目录与文件,也可以直接拿来当做更名(rename)
  • rm:remove 移除文件

# cp 复制文件或目录

cp [-adfilprsu] 来源文件(source)目标文件(destination)
cp [options] source1 source2 source3 .... directory
1
2

选项与参数:

  • a:相当于 -dr --preserve=all 的一是一,至于 dr 请参考下列说明;(常用)
  • d:若来源文件为链接文件的属性(link file),则复制链接文件属性而非文件本身
  • f:强制(force)的意思,若目标文件已经存在且无法开启,则移除后再尝试一次
  • i:若目标文件已经存在时,在覆盖时会先询问动作的进行。(常用)
  • l:进行硬式链接(hard link)的链接档的建立,而非复制文件本身
  • p:连同文件的属性(权限、用户、时间)一起复制过去,而非使用默认属性;(备份文件常用)
  • r:递归持续复制,用于目录的复制行为。(常用)
  • s:复制称为符号链接文件(symbolic link)
  • u:destination 与 source 旧才更新 destination,或 destination 不存在的情况下才复制

--preserve=all:除了 -p 的权限相关参数外,还加入 SELinux 的属性,links、xattr 等也复制

最后需要注意的是:如果来源档有两个以上,则最后一个目的文件一定要是目录才行

而且不同身份者执行这个指令会有不同的结果产生,尤其是 -a、-p 的选项,对于不同身份来说, 差异则非常的大。

实践练习

# 使用 root 身份,将家目录下的 .bashrc 复制到 /tmp 下,并更名为 bashrc
[root@study ~]# cp ~/.bashrc /tmp/bashrc
# 加上 -i 属性,由于上面已经复制过一次了,所以 bashrc 文件已经存在
[root@study ~]# cp -i ~/.bashrc /tmp/bashrc
cp:是否覆盖"/tmp/bashrc"# n 不覆盖,y 覆盖

# 变换目录到 /tmp ,并将 /var/log/wtmp 复制到 /tmp 且观察属性
[root@study tmp]# cd /tmp/
[root@study tmp]# cp /var/log/wtmp .
# ls 可以列出多个文档名,这里列出了两个,刚好可以对比他们的属性
[root@study tmp]# ls -l /var/log/wtmp wtmp
-rw-rw-r--. 1 root utmp 44160 1013 14:38 /var/log/wtmp
-rw-r--r--. 1 root root 44160 1013 15:42 wtmp
# 可以看到上面不加任何选项,被复制之后的某些属性或权限已经被改变了
# 这是个很重要的特性,要注意,文件建立的时间也不一样
# 下面将所有的属性权限都一起复制过来
[root@study tmp]# cp -a /var/log/wtmp wtmp2
[root@study tmp]# ls -l /var/log/wtmp wtmp2
-rw-rw-r--. 1 root utmp 44160 1013 14:38 /var/log/wtmp
-rw-rw-r--. 1 root utmp 44160 1013 14:38 wtmp2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

上面示例中,不加任何选项会使用预设的配置,比如常常会复制别人的数据(当然需要有 read 权限), 总是希望复制到的数据最后是我们自己的,所以上面示例才有由 utmp 变更为 root

由于具有这个特性,因此在进行备份的时候,需要特别注意的特殊权限文件,例如密码文件(/etc/shadow) 以及一些配置文件,就不能直接以 cp 来复制,需要将全部的属性都原样复制过来

# 复制 etc 目录下的所有内容
[root@study tmp]# cp /etc/ /tmp/
cp: 略过目录"/etc/"  # 提示该目录不能直接复制,要加上 -r
[root@study tmp]# cp -r /etc/ /tmp/
# 再次强调,-r 只是能递归复制,但是文件权限等属性还是会更改
# 因此可以使用 cp -a /etc/ /tmp/ 来复制,尤其是在备份的情况下
1
2
3
4
5
6

# 创建符号链接与实体链接

# 将之前复制过来的 bashrc 建立一个链接档
[root@study tmp]# pwd
/tmp
# 先查看该文件的属性
[root@study tmp]# ls -l bashrc
-rw-r--r--. 1 root root 176 1013 15:38 bashrc
# 分别建立 符号链接 和硬式链接
[root@study tmp]# cp -s bashrc bashrc_link
[root@study tmp]# cp -l bashrc bashrc_hlink
[root@study tmp]# ls -l bashrc*
# 注意看这里的数值,源文件是 1 这里变成了 2
-rw-r--r--. 2 root root 176 1013 15:38 bashrc
-rw-r--r--. 2 root root 176 1013 15:38 bashrc_hlink
# 下面这条数据,在终端中,bashrc_link 会显示浅蓝色
lrwxrwxrwx. 1 root root   6 1013 15:55 bashrc_link -> bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用 -l 及 -s 都会建立连接档(link file),那么有什么不同呢?

  • bashrc_link:使用 s 创建出来的,是符号链接(symbolic link),简单说是一个快捷方式,会链接到 bashrc 中去。有一个 -> 的符号
  • bashrc_hlink:使用 l 创建出来的,是实体链接(hard link)

实体链接与源文件的属性与权限一模一样,与尚未链接前的差异是 第二栏 的 link 由 1 变成了 2. 由于实体链接与 i-node 有关,这里先不深入了。后续文件系统部分再深入讲解

# 备份常见下的复制

当源文件比目标新的时候才复制

# 先查看两个文件的时间,可以看到源文件是 2013 年,比目标文件旧
[root@study tmp]# ls -l ~/.bashrc /tmp/bashrc
-rw-r--r--. 1 root root 176 1229 2013 /root/.bashrc
-rw-r--r--. 2 root root 176 1013 15:38 /tmp/bashrc
# 这里使用 -u 复制后,没有任何提示
[root@study tmp]# cp -u ~/.bashrc /tmp/bashrc
# 再次查看,发现没有复制成功,当前时间是 16:14 了,如果成功,目标文件的时间也会变更
[root@study tmp]# ls -l ~/.bashrc /tmp/bashrc
-rw-r--r--. 1 root root 176 1229 2013 /root/.bashrc
-rw-r--r--. 2 root root 176 1013 15:38 /tmp/bashrc
1
2
3
4
5
6
7
8
9
10

# 连接文档的复制

# 该文件是一个符号链接文件
[root@study tmp]# ls -l bashrc_link
lrwxrwxrwx. 1 root root 6 1013 15:55 bashrc_link -> bashrc
# 这里使用不加参数复制和加参数复制
[root@study tmp]# cp bashrc_link bashrc_link_1
[root@study tmp]# cp -d bashrc_link bashrc_link_2
[root@study tmp]# ls -l bashrc bashrc_link*
-rw-r--r--. 2 root root 176 1013 15:38 bashrc
lrwxrwxrwx. 1 root root   6 1013 15:55 bashrc_link -> bashrc
# 可以看到,不加参数复制把源文件复制过来了
-rw-r--r--. 1 root root 176 1013 16:16 bashrc_link_1
# 添加 -d 参数,只复制了链接文件本身
lrwxrwxrwx. 1 root root   6 1013 16:16 bashrc_link_2 -> bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13

# 多个文件同时复制到通一个目录下

cp ~/.bashrc ~/.bash_history /tmp/
1

# 身份不同执行 cp 指令表现不同

# 使用 mrcode 身份, -a 把文件原原本本的复制过来
[mrcode@study ~]$ cp -a /var/log/wtmp /tmp/mrcode_wtmp
[mrcode@study ~]$ ls -l /var/log/wtmp /tmp/mrcode_wtmp
-rw-rw-r--. 1 mrcode mrcode 44160 Oct 13 14:38 /tmp/mrcode_wtmp
-rw-rw-r--. 1 root   utmp   44160 Oct 13 14:38 /var/log/wtmp
1
2
3
4
5

胡发现其他的都一样,但是拥有者和组没有复制过来,这是因为 mrcode 身份无法进行的动作

# 小节

由于 cp 有种种的文件属性与权限的特性,所以在复制时,比必须要清楚的了解到

  • 是否需要完整的保留来源文件的信息?
  • 来源文件是否为连接档(symbolic link file)?
  • 来源档是否为特殊的文件,例如 FIFO、socket 等
  • 来源文件是否为目录?

# rm 语出文件或目录

rm [-fir] 文件或目录
1
  • f:force 强制的意思,忽略不存在的文件,不会出现警告信息
  • i:互动模式,在闪出去会询问使用者是否操作
  • r:递归删除

实践练习

# 互动模式删除
[root@study ~]# cd /tmp/
[root@study tmp]# rm -i bashrc
rm:是否删除普通文件 "bashrc"?y
# 删除的文件名还可以使用通配符, * 表示 0 个或多个
[root@study tmp]# rm -i bashrc*
rm:是否删除普通文件 "bashrc_hlink"?y
rm:是否删除符号链接 "bashrc_link"?y
rm:是否删除普通文件 "bashrc_link_1"?y
rm:是否删除符号链接 "bashrc_link_2"?y

# 删除一个目录, rmdir 无法删除非空目录
[root@study tmp]# rmdir /tmp/etc/
rmdir: 删除 "/tmp/etc/" 失败: 目录非空
# 这里使用 r 参数递归删除
[root@study tmp]# rm -r /tmp/etc/
# 但是出现了交互模式,是因为 root 身份预设加入了参数 -i
rm:是否进入目录"/tmp/etc/"? y
rm:是否删除普通文件 "/tmp/etc/fstab"?y
rm:是否删除普通空文件 "/tmp/etc/crypttab"?y
rm:是否删除符号链接 "/tmp/etc/mtab"?y
rm:是否删除普通文件 "/tmp/etc/resolv.conf"?y
rm:是否进入目录"/tmp/etc/fonts"? ^C

# 在指令前添加反斜杠,可以忽略掉 alias 的指定选项,至于 alias 后续再 bash 章节详讲
\rm -r /tmp/etc/

# 删除一个带有 - 开头的文件
# 先使用 touch 建立一个空文件
touch ./-aaa
# 注意:在 /tmp 下文件太多,常见好的文件就在最前面
ls -l
# 看到文件大小是 0 ,这是一个空文件
-rw-r--r--.  1 root   root       0 1013 19:05 -aaa-

# 删除刚才创建的,肯定不会成功的,之前讲解过 - 是个特殊字符,表示选项
[root@study tmp]# rm -aaa-
rm:无效选项 -- a
Try 'rm ./-aaa-' to remove the file "-aaa-".  # 但是这里给出了建议,添加双引号删除
Try 'rm --help' for more information.

[root@study tmp]# rm "./-aaa-"
rm:是否删除普通空文件 "./-aaa-"?y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

由于 root 的是天神,所以大部分 distribution 都默认添加了 -i 的选项,删除前请三思啊

# mv 移动文件与目录或更名

mv [-fiu]  source destination
mv [options] source1 source2 ... directory
1
2
  • f:强制,如果目标文件已经存在,不会询问,直接覆盖
  • i:若目标文件已经存在时,就会询问是否覆盖
  • u:若目标已经存在,且 source 比较新,才会功更新该文件

实践练习

[root@study tmp]# cd /tmp/   
[root@study tmp]# cp ~/.bashrc bashrc
# 创建目录
[root@study tmp]# mkdir mvtest
# 将刚刚拷贝的 bashrc 复制到目录中
[root@study tmp]# mv bashrc mvtest/
# 目录更名
# 其实还有一个指令 rename,该指令专职进行多个文档名同时更名,并非针对单一文件更名
# 与 mv 不同,详细请 man rename
[root@study tmp]# mv mvtest/ mvtest2

1
2
3
4
5
6
7
8
9
10
11

# 取得路径的文件名与目录名称,basename、dirname

每个文件的完整文档名包含了前面的目录与最终的文件名,而每个文档名的长度都可达 255 个字符, 那么怎么区分哪个是文件名?哪个是目录名?可以使用斜线「/」来分辨

一般要获取文件名或目录名称,都是些程序的手来判断用,所以这部分指令可以用在后续的 shell scripts 里面。

# /etc/sysconfig/network 比如这个路径
# 可以使用指令分别获取到他的目录与文件名
[root@study tmp]# basename /etc/sysconfig/network
network
[root@study tmp]# dirname /etc/sysconfig/network
/etc/sysconfig

1
2
3
4
5
6
7