Linux 基本文件操作

文件和目录查询

使用 ls 命令可以列出目录中的文件,不包括隐藏文件。默认按文件名排序。ll 命令是 ls -l 的别名。

以下是一些常用选项参数:

选项 说明
-a 显示隐藏文件
-d 仅查看目录本身属性
-h 使显示结果更友好
-i 列出 inode 号码
-l 显示详细信息
-n 列出 UID 与 GID
-R 连同子目录内容一起列出
-S 以文件大小排序
-t 依时间排序

可以同时查看多个文件信息,路径之间用空格隔开:

[root@101c7 ~]$ ll ./dir1/ ./audit/
./audit/:
total 360
-rw-------. 2 root root 182023 Sep 9 05:01 audit.log
lrwxrwxrwx. 1 root root 9 Sep 9 05:29 ha.log -> audit.log
-rw-------. 2 root root 182023 Sep 9 05:01 la.log

./dir1/:
total 0
-rwxrwxr--. 1 ftp root 0 Sep 8 23:29 xx

可以使用通配符 *(? 匹配单字母)来显示所有匹配的文件和目录,包括子文件夹中的文件:

[root@101c7 ~]$ ls -l s*
-rw-r--r--. 1 root root 83886080 Sep 10 22:20 sdb5.disk

sdb4m:
total 20
-rw-------. 1 root root 1260 Sep 10 15:05 a.cfg
drwx------. 2 root root 16384 Sep 10 15:03 lost+found

展示完整的文件修改时间使用 --full-time 参数:

[root@101c7 ~]$ ls -Al --full-time /etc/bash_completion.d/
total 72
-rw-r--r--. 1 root root 56178 2020-05-28 16:32:30.000000000 -0400 git
-rw-r--r--. 1 root root 829 2020-02-05 07:58:44.000000000 -0500 iprutils
-rw-r--r--. 1 root root 11736 2020-03-31 23:33:31.000000000 -0400 mercurial.sh

可以指定展示特定时间戳,比如查询文件访问时间:

[root@101c7 audit]$ ls -l --time=atime 
total 364
-rw-------. 1 root root 182023 Sep 9 05:51 b.log
-rw-r--r--. 1 root root 178 Sep 9 05:57 c.log
-rw-------. 1 root root 182023 Sep 9 05:48 mvau.log

使用 -F 参数能在文件名末显示该文件的类型:

[root@101c7 ~]$ ls -F /sbin/
accessdb*              fsfreeze*                   mkdict@ 

结果中可执行文件会在文件名后加*,软链接加@,目录加/,管道加|,并用不同颜色表示结果。

此外,还可以使用 stat 命令来查看某个文件的具体属性,其展示结果一步到位,包括文件大小、块数、I/O 块大小、设备号、Inode 号码、硬链接数量、文件权限、UID 和 GID、SELinux 安全上下文、文件访问时间、修改时间、变化时间和创建时间等信息。例如,查看 ftp.sh 文件的属性:

[root@server1 ~]$ stat ftp.sh
  File: ‘ftp.sh’
  Size: 52              Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 4215134     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2021-09-23 19:18:22.974352478 +0800
Modify: 2021-09-23 19:18:04.472546785 +0800
Change: 2021-09-23 19:18:04.473546775 +0800
 Birth: -

其中,Size 表示文件大小,Blocks 表示块数,IO Block 表示 I/O 块大小,regular file 表示文件类型为常规文件,Device 表示设备号,Inode 表示 Inode 号码,Links 表示硬链接数量,Access 表示文件访问时间,Modify 表示文件修改时间,Change 表示文件状态更改时间,Birth 表示文件创建时间。

检查文件类型

想了解某个文件的基本数据类型,可以使用 file 命令。

例如,查看二进制文件 passwd 的信息:

[root@101c7 ~]$ file /usr/bin/passwd 
/usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=dee1b9ab6618c6bfb84a14f85ba258c742cf4aec, stripped

再比如,查看日志文件 b.log 的信息:

[root@101c7 audit]$ file b.log 
b.log: ASCII text, with very long lines

复制文件与目录

使用 cp 命令可以复制文件和文件夹,系统已经为 cp 加入 -i 选项以询问用户是否覆盖文件。

例如,复制当前目录下的 anaconda-ks.cfg 文件到 /home/ 下并命名为 anac.cfg:

[root@101c7 ~]$ cp anaconda-ks.cfg /home/anac.cfg ; ll /home
total 4
-rw-------. 1 root root 1260 Sep  9 05:12 anac.cfg

复制文件夹需要使用递归参数 -r,例如复制 /var/log 下的文件夹 audit 到当前目录:

[root@101c7 ~]$ cp -r /var/log/audit/ . ; ll ./audit/
total 180
-rw-------. 1 root root 182023 Sep  9 05:14 audit.log

复制后的文件属性,如修改时间和权限(所有者变为操作者)会改变。如果要保留源文件属性,可以使用 -a 参数:

[root@101c7 ~]$ ll /var/log/audit/
total 180
-rw-------. 1 root root 182023 Sep  9 05:01 audit.log
[root@101c7 ~]$ ll audit/
total 180
-rw-------. 1 root root 182023 Sep  9 05:14 audit.log
[root@101c7 ~]$ rm -rf audit/ ; cp -ra /var/log/audit/ . ; ll audit/
total 180
-rw-------. 1 root root 182023 Sep  9 05:01 audit.log

删除文件与目录

删除文件或文件夹使用 rm 命令。如果需要删除以-开头的特殊文件,需要使用相对路径。

例如,要删除当前目录下的 la.log 和 ha.log 两个文件:

[root@101c7 audit]$ rm -f la.log ha.log

如果需要删除文件夹,则需要使用 -r 参数,并且可以使用通配符*。例如,要删除当前文件夹下以 app 开头的所有文件和文件夹:

[root@101c7 ~]$ rm -rf app*

移动和更名文件和目录

在 Linux 中,可以使用 mv 命令移动和更名文件和目录。移动文件或目录会保持其 inode 编号和时间戳不变。

例如,将文件 audit.log 移动到其上级目录并将其更名为 mvau.log:

[root@101c7 audit]$ mv audit.log ../mvau.log

也可以同时移动多个文件到指定目录。例如,将 mvau.log 和 b.log 一次性移动到目录 audit 中:

[root@101c7 ~]$ mv mvau.log b.log audit/

修改文件时间戳

在 Linux 系统中,每个文件都有三个时间戳:

属性 说明
Modification Time(mtime) 修改时间 当文件内容更改时会更新这个时间.不包括文件的属性或权限更改
Status Time(ctime) 状态(创建)时间 当文件状态改变时会更新这个时间,比如权限和属性的更改
Access Time(atime) (上次)访问时间 当文件内容读取时会更新这个时间,比如用 cat 或 less 去读取

可以使用 touch 命令来修改文件的时间戳。如果不指定时间,则修改为当前时间。

例如,将 a.log 文件的修改时间和访问时间修改为 2007 年 1 月 1 日 1 点 1 分:

[root@101c7 audit]$ ll a.log;ll --time=atime a.log; ll --time=ctime a.log 
-rw-r--r--. 1 root root 0 Sep  9 07:35 a.log
-rw-r--r--. 1 root root 0 Sep  9 07:35 a.log
-rw-r--r--. 1 root root 0 Sep  9 07:35 a.log
[root@101c7 audit]$ touch -t 0701010101 a.log
[root@101c7 audit]$ ll a.log;ll --time=atime a.log; ll --time=ctime a.log 
-rw-r--r--. 1 root root 0 Jan  1  2007 a.log
-rw-r--r--. 1 root root 0 Jan  1  2007 a.log
-rw-r--r--. 1 root root 0 Sep  9 07:38 a.log

创建文件

touch 命令本意用来更新文件时间戳,当文件不存在时会创建一个新的空文件:

[root@101c7 audit]$ touch a.log ; ll
total 364
-rw-r--r--. 1 root root      0 Sep  9 07:35 a.log

也可以使用 cat 命令接收用户输入,并将其重定向到文件中:

[root@101c7 ~]$ cat > catfile
123
32

输入完毕后按下 Ctrl+d 组合键以结束输入。

擦除文件内容

当使用 rm 命令删除文件时,实际上只是将文件的块标记为可写,而磁盘上的数据并没有被删除。如果要安全删除文件并保证不留下任何痕迹,可以使用 shred 命令,它会用随机数据对目标文件进行多次覆写。例如,以下命令对名为 www 的文件进行四次覆写,最后填充为零后再删除文件:

[root@server1 ~]$ shred -fuvz www 
shred: www: pass 1/4 (random)...
shred: www: pass 2/4 (random)...
shred: www: pass 3/4 (random)...
shred: www: pass 4/4 (000000)...
shred: www: removing
shred: www: renamed to 000
shred: 000: renamed to 00
shred: 00: renamed to 0
shred: www: removed

需要注意的是,shred 命令并不适用于所有文件系统。例如,ZFS 文件系统会为新数据分配新的数据块,而不是直接覆写旧数据。

连接文件

在 Linux 中,可以使用 ln 命令来连接文件。ln 命令有两种链接方式:硬链接和软链接。

硬连接

硬连接(hard link)是在某个目录 block 数据中新建一条文件名,连接到某个已存在的 inode 号码关联记录。

硬链接特点:

  • 新建的硬连接属性权限和源文件一样,修改也和源文件同步,是因为其数据储存在引用的 inode 块中;
  • 一个文件有几个硬连接就有几个 Link Counter;
  • 建立硬连接不占用磁盘空间与 inode 数目。

建立硬连接有两个限制:

  • 不能跨文件系统,因为不同文件系统有不同 inode;
  • 不能连接到目录。

软连接

软连接(symbolic link)也叫做符号连接或快捷方式,是指向另一个文件或目录的特殊文件。它有自己的 inode 编号和硬链接计数器。但是软链接的内容是源文件的路径名。

软连接文件属性为 l ,使用 ls 查看时会有个 -> 符号指向源文件的路径名。

如果源文件改名或删除,软链接文件将不会指向正确位置,因为其使用文件名作为引用。

目录的连接数量

当新建一个目录时,新的目录连接数为 2。

比如新建目录 /root/1/,另一个硬连接等于 /root/1/.

而上层目录的连接数会增加 1,也就是增加了 /root/1/.. 这个硬连接。

创建连接

使用 lncp 命令都可以创建连接。默认不加参数使用 ln 建立的就是硬连接:

[root@101c7 ext333]$ ln hhh hhh_hark; ll -i
total 24
16 -rw-r--r--. 2 root root     4 Sep 10 01:57 hhh
16 -rw-r--r--. 2 root root     4 Sep 10 01:57 hhh_hark
11 drwx------. 2 root root 16384 Sep  9 15:54 lost+found

创建符号连接使用参数 -s 来建立:

[root@101c7 ext333]$ ln -s hhh hhh_soft; ll -i
total 24
16 -rw-r--r--. 2 root root     4 Sep 10 01:57 hhh
16 -rw-r--r--. 2 root root     4 Sep 10 01:57 hhh_hark
12 lrwxrwxrwx. 1 root root     3 Sep 10 02:04 hhh_soft -> hhh
11 drwx------. 2 root root 16384 Sep  9 15:54 lost+found

隐藏属性

文件和文件夹主要的隐藏属性列表如下:

属性 说明
A 访问此文件的 atime 不会被修改,可避免读写较慢的机器过度访问磁盘。
S 加上此属性后,任何修改都将立即写入硬盘,不在内存中缓存。
a 设置此属性后,文件只能增加数据,不能删除也不能修改数据。设置在目录上,目录内的文件不能删除。
c 此文件会自动压缩,读取时自动解压缩。储存时会先进行压缩。
d 当 dump 执行时,此文件或目录不会被 dump 备份。
i 文件不能删除、改名、修改。设置在目录上表示不允许在目录内建立和删除文件。
s 如果文件被删除,立即将原先位置填充,完全销毁数据。
u 开启回收站功能,文件被删除后还能恢复。

上表是在 ext 文件系统中可用的属性,xfs 文件系统仅支持部分隐藏属性。

设置隐藏属性

使用 chattr 命令来给文件设置隐藏属性。例如给文件 1 加上 i 和 a 属性:

[root@101c7 ~]$ chattr +ia 1
[root@101c7 ~]$ rm -rf 1
rm: cannot remove '1': Operation not permitted

取消文件的隐藏属性 i:

[root@101c7 ~]$ chattr -i 1

如果设置对象是文件夹,使用 -R 可以递归修改,在文件夹中新建的文件会继承隐藏属性。

显示文件隐藏属性

使用 lsattr ming’l 来查看文件或目录的隐藏属性:

[root@101c7 ~]$ lsattr -R
---------------- ./anaconda-ks.cfg
---------------- ./audit

./audit:
---------------- ./audit/mvau.log
---------------- ./audit/b.log

---------------- ./2
--S--adA-------- ./3

./3:
--S--adA-------- ./3/3

--S-ia-A-------- ./1