文件查找

locate

  • locate 查询系统上预建的文件索引数据库 /var/lib/mlocate/mlocate.db
  • 索引的构建是在系统较为空闲时自动进行(周期任务),执行updatedb可以更新数据库
  • 索引构建过程需要遍历整个根文件系统,很消耗资源
  • locate和update命令来自于mlocate包

工作特点:

  • 查找速度快 模糊查找
  • 非实时查找
  • 搜索的是文件全路径,不仅仅是文件名
  • 可能只搜索用户具备读取和执行权限的目录

如果没有程序,可先安装

1
2
3
4
5
#rehl系列
yum install -y mlocate

#ubuntu
apt install -y mlocate

格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
locate [OPTION]... [PATTERN]...

#常用选项
-A|--all #输出所有能匹配到的文件名,不管文件是否存在
-b|--basename #仅匹配文件名部份,而不匹配路径中的内容
-c|--count #只输出找到的数量
-d|--database DBPATH #指定数据库
-e|--existing #仅打印当前现有文件的条目
-L|--follow #遇到软链接时则跟随软链接去其对应的目标文件中查找 (默认)
-n #指定输出的个数
-i|--ignore-case #忽略大小写
-l|--limit|-n N #只显示前N条匹配数据
-P|--nofollow, -H #不跟随软链
-q|--quiet #安静模式,不输出错误信息
-r|--regexp REGEXP #使用基本正则表达式
--regex #使用扩展正则表达式
-s|--stdio #忽略向后兼容
-w|--wholename #全路径匹配,就是只要在路径里面出现关键字(默认)

范例:locatedb创建数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@rocky8 ~]# dnf -y install mlocate
[root@rocky86 ~]# locate conf
locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory


[root@rocky8 ~]# updatedb
[root@rocky8 ~]# ll /var/lib/mlocate/mlocate.db
-rw-r----- 1 root slocate 3143608 Jun 18 08:58 /var/lib/mlocate/mlocate.db

[root@rocky8 ~]# locate -n 3 conf
/boot/config-4.18.0-348.el8.0.2.x86_64
/boot/grub2/i386-pc/configfile.mod
/boot/loader/entries/c0298860b41f4cd296da0d2853451604-0-rescue.conf

范例:文件新创建和删除,无法马上更新locate数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@rocky86 ~]# touch test.log
[root@rocky86 ~]# locate test.log


#更新数据库之后再查找
[root@rocky86 ~]# updatedb
[root@rocky86 ~]# locate test.log
/root/test.log

#文件被删除,还能查到
[root@rocky86 ~]# rm -f test.log
[root@rocky86 ~]# locate test.log
/root/test.log

#但实际上文件己经不存在了
[root@rocky86 ~]# stat /root/test.log
stat: cannot statx '/root/test.log': No such file or directory

#再次更新数据库
[root@rocky86 ~]# updatedb
[root@rocky86 ~]# locate test.log
[root@rocky86 ~]#

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#搜索名称或路径中包含“conf”的文件
[root@rocky86 ~]# locate conf

#搜索ect目录中以a开头的文件或目录
[root@rocky86 ~]# locate /etc/a

#仅搜索文件名中包含share 的内容
[root@rocky86 ~]# locate -b share

#显示数量
[root@rocky86 ~]# locate -c conf

#显示前10条
[root@rocky86 ~]# locate -n 10 conf

#使用基本正则表达式
[root@rocky86 ~]# locate -r '\.conf$'

#指定数据库
[root@rocky86 ~]# locate -d /tmp/nofile conf
locate: can not stat () `/tmp/nofile': No such file or directory

#安静模式,不输出错误信息
[root@rocky86 ~]# locate -qd /tmp/nofile conf

find

find 是实时查找工具,通过遍历指定路径完成文件查找;

工作特点:

  • 查找速度略慢
  • 精确查找
  • 实时查找
  • 查找条件丰富
  • 可能只搜索用户具备读取和执行权限的目录

格式:

1
2
3
#find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

find [OPTION]... [查找路径] [查找条件] [处理动作]

查找路径:指定具体目标路径;默认为当前目录

查找条件:指定的查找标准,可以文件名、大小、类型、权限等标准进行;默认为找出指定路径下的所有文件

处理动作:对符合条件的文件做操作,默认输出至屏幕

范例:

默认列出当前目录下的所有文件

1
2
3
4
5
6
7
8
[root@rocky8 ~]# find
.
./.vimrc
./.bash_logout
./.bash_profile
./.cshrc
./.tcshrc
./.bash_history

指定搜索目录层级

1
2
-maxdepth N             #最大搜索目录深度,指定目录下的文件为第1级
-mindepth N #最小搜索目录深度

范例:

1
2
3
4
5
6
7
8
#最大搜索深度
[root@rocky86 ~]# find /etc/ -maxdepth 2

#最小搜索深度
[root@rocky86 ~]# find /etc/ -mindepth 2

#仅搜索第二层目录
[root@rocky86 ~]# find /etc/ -maxdepth 2 -mindepth 2

先处理文件再处理目录

1
-depth      #先处理文件

范例:

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
44
45
46
[root@rocky8 ~]# mkdir -p dir1/dir2/dir3
[root@rocky8 0723]# touch {fstab,.issue,dir1/{f1,f2},dir1/dir2/{fa,fb},dir1/dir2/dir3/{fx,fy}}
[root@rocky8 0723]# tree -a
.
├── dir1
│   ├── dir2
│   │   ├── dir3
│   │   │   ├── fx
│   │   │   └── fy
│   │   ├── fa
│   │   └── fb
│   ├── f1
│   └── f2
├── fstab
└── .issue

#默认先显示目录
[root@rocky86 0723]# find
.
./dir1
./dir1/dir2
./dir1/dir2/dir3
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
./dir1/dir2/fa
./dir1/dir2/fb
./dir1/f1
./dir1/f2
./fstab
./.issue


#先显示文件
[root@rocky86 0723]# find -depth
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
./dir1/dir2/dir3
./dir1/dir2/fa
./dir1/dir2/fb
./dir1/dir2
./dir1/f1
./dir1/f2
./dir1
./fstab
./.issue
.

根据文件名和inode查找

1
2
3
4
5
6
-name name              #支持使用glob,如:*, ?, [], [^],通配符要加双引号引起来
-iname name #不区分字母大小写
-inum number #按inode号查找
-samefile name #相同inode号的文件
-links n #链接数为n的文件
-regex "PATTERN" #以PATTERN匹配整个文件路径,而非文件名称

范例:

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
44
45
46
[root@rocky8 0723]# touch test-{a,A,b,B}.log
[root@rocky8 0723]# touch test-{a,A,b,B}.txt
[root@rocky8 0723]# ls
dir1 test-a.log test-a.txt test-b.log test-b.txt
fstab test-A.log test-A.txt test-B.log test-B.txt

#指定文件名,忽略大小写
[root@rocky86 0723]# find -iname test-a.log
./test-a.log
./test-A.log

#通配符
[root@rocky86 0723]# find -name "*txt"
./test-a.txt
./test-b.txt
./test-A.txt
./test-B.txt

#通配符
[root@rocky86 0723]# find -name "test-a*"
./test-a.log
./test-a.txt

#正则表达式
[root@rocky86 0723]# find -regex ".*\.log$"
./test-a.log
./test-b.log
./test-A.log
./test-B.log

#正则表达式
[root@rocky86 0723]# find -regex ".*test-[a-z].*"
./test-a.log
./test-a.txt
./test-b.log
./test-b.txt

#正则表达式,路径匹配
[root@rocky86 0723]# find -regex ".*dir3.*"
./dir1/dir2/dir3
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy

#正则表达式,路径匹配
[root@rocky86 0723]# find -regex ".*dir3$"
./dir1/dir2/dir3

根据属主属组查找

1
2
3
4
5
6
-user USERNAME          #查找属主为指定用户(UID)的文件
-group GRPNAME #查找属组为指定组(GID)的文件
-uid UserID #查找属主为指定的UID号的文件
-gid GroupID #查找属组为指定的GID号的文件
-nouser #查找没有属主的文件
-nogroup #查找没有属组的文件

范例:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
[root@rocky86 0723]# ll dir1/
total 0
drwxr-xr-x 3 root root 38 Jul 23 10:21 dir2
-rw-r--r-- 1 123 456 0 Jul 23 10:14 f1
-rw-r--r-- 1 789 root 0 Jul 23 10:14 f2
-rw-r--r-- 1 jose root 0 Jul 23 10:48 fa.txt
-rw-r--r-- 1 jose root 0 Jul 23 10:48 fb.txt
-rw-r--r-- 1 root mage 0 Jul 23 10:48 fc.txt
-rw-r--r-- 1 root mage 0 Jul 23 10:48 fd.txt

#指定属主
[root@rocky86 0723]# find -user jose
./dir1/fa.txt
./dir1/fb.txt

#指定属主可以用 UID
[root@rocky86 0725]# find -user 1010
./fa.txt
./fb.txt

#指定属组
[root@rocky86 0723]# find -group mage
./dir1/fc.txt
./dir1/fd.txt

#指定属组可以用GID
[root@rocky86 0725]# find -group 1000
./fc.txt
./fd.txt

#指定属主属组
[root@rocky86 0723]# find -user jose -group root
./dir1/fa.txt
./dir1/fb.txt

#指定属主ID
[root@rocky86 0723]# find -uid 1010
./dir1/fa.txt
./dir1/fb.txt

#指定属组ID
[root@rocky86 0723]# find -gid 456
./dir1/f1

#指定属主属组ID
[root@rocky86 0723]# find -uid 1010 -gid 0
./dir1/fa.txt
./dir1/fb.txt

#属主用户不存在
[root@rocky86 0723]# find -nouser
./dir1/f1
./dir1/f2

#属组不在在
[root@rocky86 0723]# find -nogroup
./dir1/f1

#属主属组不存在
[root@rocky86 0723]# find -nouser -nogroup
./dir1/f1

根据文件类型查找

1
2
3
4
5
6
7
8
9
10
-type TYPE          #指定文件类型

#type 值
f #普通文件
d #目录文件
l #符号链接文件
s #套接字文件
b #块设备文件
c #字符设备文件
p #管道文件

范例:

1
2
3
4
5
6
7
8
9
#查看当前目录下的所有目录文件
[root@rocky86 0723]# find -type d
.
./dir1
./dir1/dir2
./dir1/dir2/dir3

#查找run 目录下所有管道文件
[root@rocky86 0723]# find /run/ -type p

空文件或目录

1
-empty          #空文件或空目录

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#空文件或空目录
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy
dir1/dir2/dir3/dir4

#查找空目录
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -type d
dir1/dir2/dir3/dir4

#查找空文件
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -type f
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy

组合条件

1
2
3
-a           #与,多条件默认就是与关系,可省略
-o #或
-not|! #非

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#默认 -a, 可省略
[root@rocky86 0723]# find -name "*log" -a -type f
./test-a.log
./test-b.log
./test-A.log
./test-B.log

#或
[root@rocky86 0723]# find -name "test*log" -o -name "test*txt"
./test-a.log
./test-a.txt
./test-b.log
./test-b.txt

#非
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -not -type d
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy

#非
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty ! -type d
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy

范例:配合处理动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@rocky86 0723]# find -user jose -o  -name "*log"
./dir1/fa.txt
./dir1/fb.txt
./test-a.log
./test-b.log
./test-A.log
./test-B.log

#此处 ls 只列出了后一个条件的匹配
[root@rocky8 0723]# find -user jose -o -name "*.log" -ls
816459 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-a.log
816460 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-A.log
816461 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-b.log
816462 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-B.log

#把条件括起来才表示全部
[root@rocky8 0723]# find \( -user jose -o -name "*.log" \) -ls
134688729 0 -rw-r--r-- 1 jose root 0 Oct 13 17:52 ./dir1/fa.txt
134688730 0 -rw-r--r-- 1 jose root 0 Oct 13 17:53 ./dir1/fb.txt
816459 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-a.log
816460 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-A.log
816461 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-b.log
816462 0 -rw-r--r-- 1 root root 0 Oct 13 16:55 ./test-B.log

德·摩根定律:

  • (非A)且(非B)=非(A或B)
  • (非A)或(非B)=非(A且B)

示例:

1
2
!A -a !B = !(A -o B)
!A -o !B = !(A -a B)

示例:

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
 # !A -a !B
[root@rocky8 0723]# find ! -name "f*" -a ! -name "dir*"
.
./.issue
./test-a.log
./test-A.log
./test-b.log
./test-B.log
./test-a.txt
./test-A.txt
./test-b.txt
./test-B.txt

# !(A -o B)
[root@rocky8 0723]# find ./ ! \( -name "f*" -o -name "dir*" \)
./
./.issue
./test-a.log
./test-A.log
./test-b.log
./test-B.log
./test-a.txt
./test-A.txt
./test-b.txt
./test-B.txt

# !A -o !B
[root@rocky8 0723]# find ! -type f -o ! -empty
.
./dir1
./dir1/dir2
./dir1/dir2/dir3

# !(A -a B)
[root@rocky8 0723]# find ! \( -type f -a -empty \)
.
./dir1
./dir1/dir2
./dir1/dir2/dir3

排除目录

1
-prune          #跳过,排除指定目录,必须配合 -path使用

范例:

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
#查找所有 txt文件
[root@rocky86 0723]# find -name "*.txt"
./dir1/fa.txt
./dir1/fb.txt
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt

#排除 dir1 目录中的 txt 文件,但还是会输出 dir1
[root@rocky86 0723]# find -path './dir1' -prune -o -name "*.txt"
./dir1
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt

#action 作用在后一个条件上
[root@rocky86 0723]# find -path './dir1' -prune -o -name "*.txt" -print
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt

#排除多个目录
[root@rocky86 0723]# find \( -path './dir1' -o -path './dir4' \) -prune -o -name "*.txt" -print
./test-a.txt
./test-b.txt

根据文件大小来查找

1
2
3
4
5
6
-size [+|-]N UNIT           # N为数字,UNIT为常用单位 k, M, G, c(byte) 等

#解释
10k #表示(9k,10k],大于9k 且小于或等于10k
-10k #表示[0k,9k],大于等于0k 且小于或等于9k
+10k #表示(10k,∞),大于10k

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 #大于4K,小于或等于5K的文件
[root@rocky8 0723]# find /var/log/ -size 5k -ls
335686295 8 -rw-r----- 1 root root 4464 Sep 9 15:21 /var/log/firewalld
269307741 8 -rw-r--r-- 1 root root 4685 Sep 9 15:41 /var/log/httpd/access_log-20240918
269184430 8 -rw-r--r-- 1 root root 4321 Sep 29 09:10 /var/log/httpd/error_log-20240929

#小于或等于2k
[root@rocky8 0723]# find /var/log/ -size -3k -name "*gz" -ls
473414 4 -rw------- 1 root root 239 Sep 29 08:13 /var/log/sssd/sssd_implicit_files.log-20240929.gz


#大于2k
[root@rocky8 0723]# find /var/log/ -size +2k -name "*.gz" -ls
473419 12 -rw------- 1 root root 9617 Sep 29 09:10 /var/log/sssd/sssd.log-20240929.gz
808277 8 -rw------- 1 root root 5783 Sep 29 08:13 /var/log/sssd/sssd_nss.log-20240929.gz

#大于2k,小于或等于9k
[root@rocky8 0723]# find /var/log/ -size +2k -size -10k -name "*.gz" -ls
808277 8 -rw------- 1 root root 5783 Sep 29 08:13 /var/log/sssd/sssd_nss.log-20240929.gz

根据时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#以天为单位
-atime [+|-]N
-mtime [+|-]N
-ctime [+|-]N

#以分钟为单位
-amin [+|-]N
-mmin [+|-]N
-cmin [+|-]N

#解释
N #表示[N,N+1),大于或等于N,小于N+1,表示第N天(分钟)
+N #表示[N+1,∞],大于或等于N+1,表示N+1天之前(包括)
-N #表示[0,N),大于或等于0,小于N,表示N天(分钟)内

范例:

1
2
3
4
5
 #查找五分钟内被访问过的文件
[root@rocky86 0724]# find -amin -5

#查找十分钟前被访问过的文件
[root@rocky86 0724]# find -amin +10

1

根据权限查找

1
2
3
4
5
6
7
8
-perm [/|-]MODE

MODE #精确权限匹配
/MODE #任何一类(u,g,o)对象的权限中只要有一位匹配即可,表示或者(or)关系
+MODE #从CentOS 7开始己淘汰
-MODE #每一类对象都必须同时拥有指定权限,表示与(and)关系

#0 如果要找时权限位上的值为0,则表示不关注该角色权限

范例:

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
44
45
46
47
48
49
50
51
[root@rocky86 0724]# ll
total 0
---------- 1 root root 0 Jul 25 09:12 f-1.txt
-r--r--r-- 1 root root 0 Jul 25 09:12 f-2.txt
--w--w--w- 1 root root 0 Jul 25 09:12 f-3.txt
---x--x--x 1 root root 0 Jul 25 09:17 f-4.txt
-rw-r--r-- 1 root root 0 Jul 25 09:17 f-5.txt
-rwxrwxrwx 1 root root 0 Jul 25 09:17 f-6.txt
-r---w---x 1 root root 0 Jul 25 09:22 f-8.txt

#精确匹配,ugo都只能是 r权限
[root@rocky8 0723]# find -perm 444 -ls
816460 0 -r--r--r-- 1 root root 0 Oct 13 18:41 ./f-2.txt

#或关系,ugo只要有一个角色有r权限即可
[root@rocky8 0723]# find -perm /444 -ls
816458 0 drwxr-xr-x 2 root root 125 Oct 13 18:43 .
402653958 0 -rw-r--r-- 1 root root 0 Oct 13 16:52 ./.issue
816460 0 -r--r--r-- 1 root root 0 Oct 13 18:41 ./f-2.txt
816463 0 -rw-r--r-- 1 root root 0 Oct 13 18:41 ./f-5.txt
816464 0 -rwxrwxrwx 1 root root 0 Oct 13 18:41 ./f-6.txt
816466 0 -r---w---x 1 root root 0 Oct 13 18:41 ./f-8.txt

#报错
[root@rocky8 0723]# find -perm +444 -ls
find: invalid mode ‘+444’

#ugo三个角色至少都要有r权限
[root@rocky8 0723]# find -perm -444 -ls
816458 0 drwxr-xr-x 2 root root 125 Oct 13 18:43 .
402653958 0 -rw-r--r-- 1 root root 0 Oct 13 16:52 ./.issue
816460 0 -r--r--r-- 1 root root 0 Oct 13 18:41 ./f-2.txt
816463 0 -rw-r--r-- 1 root root 0 Oct 13 18:41 ./f-5.txt
816464 0 -rwxrwxrwx 1 root root 0 Oct 13 18:41 ./f-6.txt

#只关注属主权限,6拆分成4+2,所以只要属主有r或w权限即可
[root@rocky8 0723]# find -perm /600 -ls
816458 0 drwxr-xr-x 2 root root 125 Oct 13 18:43 .
402653958 0 -rw-r--r-- 1 root root 0 Oct 13 16:52 ./.issue
816460 0 -r--r--r-- 1 root root 0 Oct 13 18:41 ./f-2.txt
816461 0 --w--w--w- 1 root root 0 Oct 13 18:41 ./f-3.txt
816463 0 -rw-r--r-- 1 root root 0 Oct 13 18:41 ./f-5.txt
816464 0 -rwxrwxrwx 1 root root 0 Oct 13 18:41 ./f-6.txt
816466 0 -r---w---x 1 root root 0 Oct 13 18:41 ./f-8.txt

#只关注属主权限,6拆分成4+2,所以只要属主至少要有有rw权限
[root@rocky8 0723]# find -perm -600 -ls
816458 0 drwxr-xr-x 2 root root 125 Oct 13 18:43 .
402653958 0 -rw-r--r-- 1 root root 0 Oct 13 16:52 ./.issue
816463 0 -rw-r--r-- 1 root root 0 Oct 13 18:41 ./f-5.txt
816464 0 -rwxrwxrwx 1 root root 0 Oct 13 18:41 ./f-6.txt

正则表达式

1
2
-regextype type         #正则表达式类型,emacs|posix-awk|posix-basic|posix-egrep|posix-extended
-regex pattern #正则表达式

范例:

1
2
3
4
5
[root@rocky86 0724]# find -regextype posix-egrep -regex ".*log"
./ls.log

[root@rocky86 0724]# find -regextype posix-egrep -regex ".*5.*"
./f-5.txt

处理动作

1
2
3
4
5
6
7
8
-print                  #默认的处理动作,显示至屏幕
-print0 #不换行输出,常用于配合xargs
-ls #类似于对查找到的文件执行"ls -ils"命令格式输出
-fls file #查找到的所有文件的长格式信息保存至指定文件中,相当于 -ls > file
-delete #删除查找到的文件,慎用!
-ok COMMAND {} \; #对查找到的每个文件执行由COMMAND指定的命令,对于每个文件执行命令之前,都会交互式要求用户确认
-exec COMMAND {} \; #对查找到的每个文件执行由COMMAND指定的命令
{} #用于引用查找到的文件名称自身

范例:

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
#默认 -print
[root@rocky86 0724]# find
.
./f-1.txt
./f-2.txt
./f-3.txt

#长格式显示
[root@rocky8 0723]# find -ls
816458 0 drwxr-xr-x 2 root root 125 Oct 13 18:43 .
402653958 0 -rw-r--r-- 1 root root 0 Oct 13 16:52 ./.issue
816459 0 ---------- 1 root root 0 Oct 13 18:41 ./f-1.txt
816460 0 -r--r--r-- 1 root root 0 Oct 13 18:41 ./f-2.txt

#查找结果保存至文件
[root@rocky86 0724]# find -fls ls.log

#删除
[root@rocky86 0724]# find -name "*.sh" -delete

#备份以log结尾的文件
[root@rocky86 0724]# find -name "*log" -exec cp {} {}.bak \;

[root@rocky86 0724]# ls *log*
f-1.log f-1.log.bak f-2.log f-2.log.bak f-3.log f-3.log.bak

#删除15分钟内没被访问过的文件
[root@rocky86 0724]# find -amin +15 -ok rm {} \;
< rm ... ./f-1.txt > ?

#将other权限有w的文件的权限去掉w权限
[root@rocky86 0724]# find -perm -002 -exec chmod o-w {} \;

#查找权限为644,后缀为sh的普通文件,增加执行权限
[root@rocky86 0724]# find -type f -perm 644 -name "*.sh" -exec chmod 755 {} \;

参数替换xargs

由于很多命令不支持管道|来传递参数,为了使用更灵活的参数,我们就城要用 xargs 产生命令参数,

xargs 可以读入 stdin 的数据,并且以空格符或回车符将 stdin 的数据分隔,使其成为另一个命令的参数,

另外,许多命令不能接受过多参数,命令执行可能会失败,xargs 也可以解决此问题;

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
xargs [OPTION]... COMMAND [INITIAL-ARGS]...

#常用选项
-0|--null #用 assic 中的0或 null 作分隔符
-a|--arg-file=FILE #从文件中读入作为输入
-d|--delimiter=CHARACTER #指定分隔符
-E END #指定结束符,执行到此处时停止,不管后面的数据
-L|--max-lines=N #从标准输入一次读取N行送给 command 命令
-l #同上
-n|--max-args=MAX-ARGS #一次执行用几个参数
-p|--interactive #每次执行前确认
-r|--no-run-if-empty #当xargs的输入为空的时候则停止xargs,不用再去执行了
-s|--max-chars=MAX-CHARS #命令行最大字符数
-t|--verbose #显示过程,先打印要执行的命令
-x|--exit #退出,主要配合-s使用

范例:

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
[root@rocky86 0724]# ls f-1.log
f-1.log

#无法用管道传参
[root@rocky86 0724]# echo "f-1.log" | ls
...
...

#命令展开
[root@rocky86 0724]# ls `echo f-1.txt`
f-1.txt

#xargs
[root@rocky86 0724]# echo "f-1.log" | xargs ls
f-1.log

#还可以让不支持标准输入的命令支持标输输入(ctrl+d 结束)
[root@rocky86 0724]# xargs ls -l
f-1.log
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-1.log

#让命令支持标准输入重定向
[root@rocky86 0724]# cat ls.log
f-1.log
f-2.log

[root@rocky86 0724]# xargs -a ls.log ls -l
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-1.log
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-2.log

范例:

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
[root@rocky86 0724]# seq 3
1
2
3

[root@rocky86 ~]# seq 3 | xargs
1 2 3

#指定分割符
[root@rocky86 ~]# echo -e "1-2-3\c" | xargs -d '-'
1 2 3

[root@rocky86 0724]# echo {1..5}
1 2 3 4 5

[root@rocky86 0724]# echo {1..5} | xargs
1 2 3 4 5

#指定每次使用2个参数
[root@rocky86 0724]# echo {1..5} | xargs -n 2
1 2
3 4
5

#批量创建用户并显示命令
[root@rocky86 0724]# echo user{1..5} |xargs -t -n1 useradd
useradd user1
useradd user2
useradd user3
useradd user4
useradd user5

#批量删除用户
[root@rocky86 0724]# echo user{1..5} |xargs -n1 userdel -r

范例:批量创建文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@rocky8 0723]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
devtmpfs 224364 398 223966 1% /dev
tmpfs 229154 1 229153 1% /dev/shm
tmpfs 229154 612 228542 1% /run
tmpfs 229154 17 229137 1% /sys/fs/cgroup
/dev/mapper/rl-root 68157440 61837 68095603 1% /
/dev/sda1 524288 310 523978 1% /boot
/dev/mapper/rl-home 34078720 51 34078669 1% /home
tmpfs 229154 5 229149 1% /run/user/0

#参数太长,执行失败
[root@rocky86 test]# touch f-{1..523975}.txt
-bash: /usr/bin/touch: Argument list too long

#一次创建1w个
[root@rocky86 test]# echo f-{1..523975}.txt | xargs -n 10000 touch

#inode 资源耗尽
[root@rocky86 test]# df -i

范例:批量下载B站视频

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@rocky86 ~]# yum install python3-pip -y
[root@rocky86 ~]# pip3 install you-get

#如果前一条install报错,可以用这个
[root@rocky86 ~]# pip3 --default-timeout=100 install -U you-get

# 还是报错的话,安装开发库
sudo dnf update
sudo dnf install python3-devel


#批量下载 后面的是视频链接
[root@rocky86 ~]# seq 60 | xargs -i -P3 you-get https://www.bilibili.com/video/BV14K411W7UF?p={}

范例:以 ascii中的空白符分隔参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@rocky86 0724]# ls
'a b' f-1.txt f-2.txt f-3.txt

[root@rocky86 0724]# find -type f | xargs echo
./f-1.txt ./f-2.txt ./f-3.txt ./a b

#在此处有空格的文件名被拆分成两个文件了,xargs 默认以空格拆分
[root@rocky86 0724]# find -type f | xargs ls
ls: cannot access './a': No such file or directory
ls: cannot access 'b': No such file or directory
./f-1.txt ./f-2.txt ./f-3.txt

#正常显示
[root@rocky86 0724]# find -type f -print0 |xargs -0 ls
'./a b' ./f-1.txt ./f-2.txt ./f-3.txt

练习

  1. 查找/var目录下属主为root,且属组为mail的所有文件
  2. 查找/var目录下不属于root、lp、gdm的所有文件
  3. 查找/var目录下最近一周内其内容修改过,同时属主不为root,也不是postfix的文件
  4. 查找当前系统上没有属主或属组,且最近一个周内曾被访问过的文件
  5. 查找/etc目录下大于1M且类型为普通文件的所有文件
  6. 查找/etc目录下所有用户都没有写权限的文件
  7. 查找/etc目录下至少有一类用户没有执行权限的文件
  8. 查找/etc/init.d目录下,所有用户都有执行权限,且其它用户有写权限的文件

压缩和解压缩

主要针对单个文件压缩,而非目录

compress 和 uncompress

此工具来自于ncompress包,此工具目前已经很少使用

对应的文件是 .Z 后缀

格式

1
2
3
4
5
6
7
#常用选项

-d #解压缩,相当于于uncompress
-c #结果输出至标准输出,不删除原文件
-f #覆盖己存在目标文件
-v #显示过程
-r #递归压缩目录里面所有文件

范例:

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
[root@rocky86 0726]# ls
fstab

#默认选项压缩
[root@rocky86 0726]# compress fstab
[root@rocky86 0726]# ls
fstab.Z

#解压缩
[root@rocky86 0726]# uncompress fstab.Z
[root@rocky86 0726]# ls
fstab

#显示过程
[root@rocky86 0726]# compress -v fstab
fstab: -- replaced with fstab.Z Compression: 33.88%

#解压缩
[root@rocky86 0726]# compress -dv fstab.Z
fstab.Z: -- replaced with fstab

#保留源文件
[root@rocky86 0726]# compress -c fstab > fstab.Z
[root@rocky86 0726]# ls
fstab fstab.Z

范例:递归压缩目录

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
[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│ └── messages
├── dnf.log
├── fstab
└── passwd
1 directory, 4 files

[root@rocky86 0726]# compress -vr dir1/
dir1//dir2/messages: -- replaced with dir1//dir2/messages.Z Compression: 71.74%
dir1//fstab: -- replaced with dir1//fstab.Z Compression: 33.88%
dir1//dnf.log: -- replaced with dir1//dnf.log.Z Compression: 80.21%
dir1//passwd: -- replaced with dir1//passwd.Z Compression: 45.24%

[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│ └── messages.Z
├── dnf.log.Z
├── fstab.Z
└── passwd.Z
1 directory, 4 files

#递归解压缩目录
[root@rocky86 0726]# compress -drv dir1/
dir1//dir2/messages.Z: -- replaced with dir1//dir2/messages
dir1//fstab.Z: -- replaced with dir1//fstab
dir1//dnf.log.Z: -- replaced with dir1//dnf.log
dir1//passwd.Z: -- replaced with dir1//passwd

gzip和gunzip

来自于 gzip 包

对应的文件是 .gz 后缀

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gzip [OPTION]... FILE ...
gunzip [OPTION]... FILE ...

#常用选项
-c|--stdout #将压缩数据输出到标准输出中,并保留原文件
-d|--decompress #解压缩,相当于gunzip
-f|--force #覆盖己存在目标文件
-k|--keep #保留原文件
-l|--list #显示原文件大小,压缩文件大小,压缩比,压缩前文件名
-q|--quiet #安静模式,忽略警告
-r|--recursive #递归压缩目录内所有文件
-S|--suffix=SUF #指定压缩文件后缀
-t|--test #测试,检测压缩文件是否完整
-v|--verbose #显示过程
-1|--fast #最快压缩,压缩比最底,但压缩速度快
-9|--best #最好压缩,压缩比最高,但压缩速度慢
-N #指定压缩等级,取值为1-9之间,默认6

范例:

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
#保留原文件,并显示压缩过程
[root@rocky86 0726]# gzip -vk fstab passwd
fstab: 50.3% -- created fstab.gz
passwd: 61.2% -- created passwd.gz

[root@rocky86 0726]# ls
dir1 fstab fstab.gz passwd passwd.gz shadow

#重定向到文件
[root@rocky86 0726]# gzip fstab -c > fstab.gz

#管道
[root@rocky86 0726]# cat passwd | gzip > pwd.gz

#自定义后缀名
[root@rocky86 0726]# gzip -kv fstab -S .gzzz
fstab: 50.3% -- created fstab.gzzz

#递归压缩目录
[root@rocky86 0726]# gzip -vrk dir1/
dir1/dir2/messages: 86.1% -- created dir1/dir2/messages.gz
dir1/fstab: 50.3% -- created dir1/fstab.gz
dir1/dnf.log: 91.2% -- created dir1/dnf.log.gz
dir1/passwd: 61.2% -- created dir1/passwd.gz

#显示压缩文件信息
[root@rocky86 0726]# gzip -l fstab.gz
compressed uncompressed ratio uncompressed_name
382 720 50.3% fstab

[root@rocky86 0726]# gzip -l fstab.gz passwd.gz
compressed uncompressed ratio uncompressed_name
382 720 50.3% fstab
1134 2858 61.2% passwd
1516 3578 58.3% (totals)

范例:

1
2
3
4
 #解压缩
[root@rocky86 0726]# gunzip -vkf fstab.gz passwd.gz
fstab.gz: 50.3% -- replaced with fstab
passwd.gz: 61.2% -- replaced with passwd

bzip2和bunzip2

来自于 bzip2 包

对应的文件是 .bz2 后缀

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bzip2 [OPTION]... FILE ...
bunzip2 [OPTION]... FILE ...

#常用选项
-d|--decompress #解压缩,相当于bunzip2
-z|--compress #强制压缩
-k|--keep #保留原文件
-f|--force #覆盖己存在目标文件
-t|--test #测试,检测压缩文件是否完整
-c|--stdout #将压缩数据输出到标准输出中,并保留原文件
-q|--quiet #安静模式,忽略警告
-v|--verbose #显示过程
-N #指定压缩等级,取值为1-9之间,默认9
--fast #同 -1
--best #同 -9

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#保留原文件,并显示过程
[root@rocky86 0726]# bzip2 -kv fstab passwd
fstab: 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.
passwd: 2.516:1, 3.180 bits/byte, 60.25% saved, 2858 in, 1136 out.

#输出重定向
[root@rocky86 0726]# bzip2 fstab -cv > fstab.bz2
fstab: 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.

#管道+输出重寅
[root@rocky86 0726]# cat fstab | bzip2 -cv >fstab.bz2
(stdin): 1.731:1, 4.622 bits/byte, 42.22% saved, 720 in, 416 out.

#解压缩
[root@rocky86 0726]# bunzip2 -kfv fstab.bz2
fstab.bz2: done

#不解压查看文件内容
[root@rocky86 0726]# bzcat fstab.bz2

xz 和 unxz

来自于 xz 包

对应的文件是 .xz 后缀

格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
xz [OPTION]... FILE ...
unxz [OPTION]... FILE ...

#常用选项
-z|--compress #强制压缩
-d|--decompress #解压缩,相当于unxz
-t|--test #测试,检测压缩文件是否完整
-l|--list #查看压缩文件相关信息
-k|--keep #保留原文件
-f|--force #覆盖己存在目标文件
-c|--stdout #将压缩数据输出到标准输出中,并保留原文件
-T|--threads=NUM #开多线程,默认1
-q|--quiet #安静模式,忽略警告
-v|--verbose #显示过程
-N #指定压缩等级,取值为1-9之间,默认6

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#保留原文件
[root@rocky86 0726]# xz -kv messages
messages (1/1)
100 % 29.5 KiB / 393.1 KiB = 0.075

#查看
[root@rocky86 0726]# xz -l messages.xz
Strms Blocks Compressed Uncompressed Ratio Check Filename
1 1 29.5 KiB 393.1 KiB 0.075 CRC64 messages.xz

#重定向
[root@rocky86 0726]# xz -kcv messages > msg.xz
messages (1/1)
100 % 29.5 KiB / 393.1 KiB = 0.075

#解压缩
[root@rocky86 0726]# unxz -vfk fstab.xz msg.xz
fstab.xz (1/2)
100 % 444 B / 720 B = 0.617
msg.xz (2/2)
100 % 29.5 KiB / 393.1 KiB = 0.075

zip 和 unzip

zip 可以实现打包目录和多个文件成一个文件并压缩,但可能会丢失文件属性信息,如:所有者和组信息

分别来自于 zip 和 unzip 包

对应的文件是 .zip 后缀

格式:

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
44
45
46
47
48
 zip [OPTION]... zipfile [FILE]...
unzip [OPTION]... zipfile [FILE]...


#zip常用选项
-f #更换较新的文件到压缩文件内
-u #如果压缩包内有,则更新,如果没有,则追加进去
-d #从压缩包内删除指定的文件
-m #将文件压缩之后,删除原始文件
-r #递归压缩目录
-j #只保存文件名称及其内容,而不存放任何目录名称
-l #压缩文件时,把LF字符置换成LF+CR字符,unzip -l 表示显示压缩文件的内容
-1 #最快压缩,数字1
-9 #最高压缩比,数字9
-q #安静模式
-v #显示过程
-c #替每个被压缩的文件加上注释
-z #给压缩包加注释,unzip -z 查看注释
-x #压缩时排除指定文件
-i #仅压缩指定文件
-D #压缩文件内不建立目录名称
-T #测试,检测压缩文件是否完整
-X #不保存额外的文件属性
-y #直接保存符号连接,而非该链接所指向的文件
-n #不压缩以特定字符串结尾的文件
-P #加密码



#unzip常用选项
-p #将压缩内容通过管道传送
-l #显示压缩文件内所包含的文件
-t #测试,检测压缩文件是否完整
-z #查看注释
-v #列出包内文件信息
-x #指定不需要解压缩的文件
-d #指定解压后的目标目录
-n #解压缩时不要覆盖原有的文件
-q #安静模式
-o #直接覆盖
-a #对文本文件进行必要的字符转换
-j #不处理压缩文件中原有的目录路径
-C #压缩文件中的文件名称区分大小写
-L #将压缩文件中的全部文件名改为小写
-X #解压缩时同时回存文件原来的UID/GID
-V #保留VMS的文件版本信息
-K #解压缩后还原权限
-M #将输出结果送到more程序处理

范例:

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
[root@rocky86 0726]# zip -v msg.zip messages 
adding: messages (in=402508) (out=56530) (deflated 86%)
total bytes=402508, compressed=56530 -> 86% savings

#查看内容
[root@rocky86 0726]# unzip -l msg.zip
Archive: msg.zip
Length Date Time Name
--------- ---------- ----- ----
402508 07-26-2022 09:03 messages
--------- ------
402508 1 file

#管道,往压缩包中添加新文件
[root@rocky86 0726]# cat passwd | zip msg.zip passwd

#查看
[root@rocky86 0726]# unzip -l msg.zip
Archive: msg.zip
Length Date Time Name
--------- ---------- ----- ----
402508 07-26-2022 09:03 messages
2858 07-25-2022 22:09 passwd
--------- -------
405366 2 files

#只压缩txt
[root@rocky86 0726]# zip -i"*txt" txt.zip *
adding: f1.txt (deflated 86%)
adding: f2.txt (deflated 86%)
adding: f3.txt (deflated 86%)

#只压缩txt
[root@rocky86 0726]# zip txt2.zip ./*txt
adding: f1.txt (stored 0%)
adding: f2.txt (deflated 86%)
adding: f3.txt (deflated 86%)

范例:递归压缩

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
44
45
46
47
48
49
50
51
52
53
54
55
56
[root@rocky86 0726]# tree dir1/
dir1/
├── dir2
│ └── messages
├── dnf.log
├── fstab
└── passwd

1 directory, 4 files

#递归压缩
[root@rocky86 0726]# zip -r test1.zip dir1/
adding: dir1/ (stored 0%)
adding: dir1/dir2/ (stored 0%)
adding: dir1/dir2/messages (deflated 86%)
adding: dir1/fstab (deflated 50%)
adding: dir1/passwd (deflated 61%)
adding: dir1/dnf.log (deflated 91%)

#当前目录所有文件
[root@rocky86 0726]# cd dir1/
[root@rocky86 dir1]# zip ../test2.zip *
adding: dir2/ (stored 0%)
adding: dnf.log (deflated 91%)
adding: fstab (deflated 50%)
adding: passwd (deflated 61%)

[root@rocky86 dir1]# cd ..
[root@rocky86 0726]# ll test*
-rw-r--r-- 1 root root 76768 Jul 26 15:02 test1.zip
-rw-r--r-- 1 root root 46255 Jul 26 15:02 test2.zip

#查看
[root@rocky86 0726]# unzip -l test1.zip
Archive: test1.zip
Length Date Time Name
--------- ---------- ----- ----
0 07-26-2022 15:01 dir1/
0 07-25-2022 22:30 dir1/dir2/
216607 07-25-2022 21:41 dir1/dir2/messages
720 07-25-2022 21:39 dir1/fstab
2858 07-25-2022 21:43 dir1/passwd
501645 07-25-2022 21:40 dir1/dnf.log
--------- ------
721830 6 files

[root@rocky86 0726]# unzip -l test2.zip
Archive: test2.zip
Length Date Time Name
--------- ---------- ----- ----
0 07-25-2022 22:30 dir2/
501645 07-25-2022 21:40 dnf.log
720 07-25-2022 21:39 fstab
2858 07-25-2022 21:43 passwd
--------- ------
505223 4 files

范例:设置密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 #非交互式加密解密
[root@rocky86 dir1]# zip -vP 123456 test.zip dnf.log
adding: dnf.log (in=501645) (out=44208) (deflated 91%)
total bytes=501645, compressed=44220 -> 91% savings

[root@rocky86 dir1]# unzip -P 123456 test.zip
Archive: test.zip
inflating: dnf.log

#交互式加密解密
[root@rocky86 dir1]# zip -ve test.zip dnf.log
Enter password:
Verify password:
updating: dnf.log (in=501645) (out=44208) (deflated 91%)
total bytes=501645, compressed=44220 -> 91% savings

[root@rocky86 dir1]# unzip test.zip
Archive: test.zip
[test.zip] dnf.log password:
inflating: dnf.log

范例:更新和删除

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[root@rocky86 0726]# unzip -l txt.zip 
Archive: txt.zip
Length Date Time Name
--------- ---------- ----- ----
2226376 07-26-2022 14:12 f1.txt
1946847 07-26-2022 14:09 f2.txt
1814952 07-26-2022 14:09 f3.txt
--------- ------
5988175 3 files

[root@rocky86 0726]# echo "123">f1.txt
[root@rocky86 0726]# ll f1.txt passwd
-rw------- 1 root root 4 Jul 26 14:19 f1.txt
-rw-r--r-- 1 root root 2858 Jul 25 22:09 passwd

#如果包内不存在,则追加
[root@rocky86 0726]# zip -vu txt.zip f1.txt passwd
updating: f1.txt (in=4) (out=4) (stored 0%)
adding: passwd (in=2858) (out=1109) (deflated 61%)
total bytes=3764661, compressed=525257 -> 86% savings

#再次查看,f1.txt 更新了
[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length Date Time Name
--------- ---------- ----- ----
4 07-26-2022 14:19 f1.txt
1946847 07-26-2022 14:09 f2.txt
1814952 07-26-2022 14:09 f3.txt
2858 07-25-2022 22:09 passwd
--------- -------
3764661 4 files

#仅更新,不追加新文件
[root@rocky86 0726]# zip -vf txt.zip f1.txt messages
freshening: f1.txt (in=7) (out=7) (stored 0%)
total bytes=3764664, compressed=525260 -> 86% savings

#messages没有被追加到压缩文件内
[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length Date Time Name
--------- ---------- ----- ----
7 07-26-2022 14:24 f1.txt
1946847 07-26-2022 14:09 f2.txt
1814952 07-26-2022 14:09 f3.txt
2858 07-25-2022 22:09 passwd
--------- ------
3764664 4 files

#从 txt.zip 中删除 f3.txt
[root@rocky86 0726]# zip -d txt.zip f3.txt
deleting: f3.txt

[root@rocky86 0726]# unzip -l txt.zip
Archive: txt.zip
Length Date Time Name
--------- ---------- ----- ----
7 07-26-2022 14:24 f1.txt
1946847 07-26-2022 14:09 f2.txt
2858 07-25-2022 22:09 passwd
--------- ------
1949712 3 files

范例:注释

1
2
3
4
5
6
7
8
9
 #添加注释信息,ctrl+d结束
[root@rocky86 0726]# zip -z txt.zip
enter new zip file comment (end with .):
this is test des

#查看注释,unzip -l 也可查看
[root@rocky86 0726]# unzip -z txt.zip
Archive: txt.zip
this is test des

范例:解压缩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#指定解压目录,不解压指定文件
[root@rocky86 0726]# unzip txt.zip -x f3.txt -d ./txt
Archive: txt.zip
inflating: ./txt/f1.txt
inflating: ./txt/f2.txt

[root@rocky86 0726]# ll txt
total 1912
-rw-r--r-- 1 root root 4453 Jul 26 15:19 f1.txt
-rw------- 1 root root 1946847 Jul 26 14:09 f2.txt

#查看
[root@rocky86 0726]# unzip -v txt.zip
Archive: txt.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
4453 Defl:N 1661 63% 07-26-2022 15:19 a30efa6e f1.txt
1946847 Defl:N 269213 86% 07-26-2022 14:09 add171e4 f2.txt
1814952 Defl:N 254931 86% 07-26-2022 14:09 eb2f160b f3.txt
-------- ------- --- ------
3766252 525805 86% 3 files

zcat

zcat 来源于 “zip cat” 的缩写,见字知义

其功能是在不解压的情况下查看压缩文件内容

格式:

1
2
3
4
5
6
7
8
zcat [OPTION]... [FILE]...

#常用选项
-c #将内容输出到标准输出,默认
-d #解压缩
-l #显示压缩文件(包)内的文件列表
-r #在目上递归操作
-t #测试压缩文件完整性

示例:

1
2
3
[root@rocky86 0726]# zcat fstab.Z 
[root@rocky86 0726]# zcat fstab.gz
[root@rocky86 0726]# zcat fstab.zip

压缩率比较

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@rocky86 0725]# compress hwdb.bin -vc > hwdb.bin.Z
[root@rocky86 0725]# gzip -kv hwdb.bin
[root@rocky86 0725]# bzip2 -kv hwdb.bin
[root@rocky86 0725]# xz -kv hwdb.bin
[root@rocky86 0725]# zip -v hwdb.zip hwdb.bin

[root@rocky86 0725]# ll hwdb.* -h -S
-r--r--r-- 1 root root 11M Jul 26 20:48 hwdb.bin
-rw-r--r-- 1 root root 2.8M Jul 26 21:40 hwdb.bin.Z
-rw-r--r-- 1 root root 2.0M Jul 26 21:41 hwdb.zip
-r--r--r-- 1 root root 2.0M Jul 26 20:48 hwdb.bin.gz
-r--r--r-- 1 root root 1.7M Jul 26 20:48 hwdb.bin.bz2
-r--r--r-- 1 root root 1.4M Jul 26 20:48 hwdb.bin.xz

打包和解包

tar

tar 即 Tape ARchive 磁带归档,可以对目录和多个文件打包成一个文件进行归档;

其本身不具备压缩功能,但可以使用参数调用相应的压缩命令进行压缩;

此命令可以保留文件属性,推荐使用;

对应的文件是 .tar 后缀

格式:

1
2
tar [OPTION...] [FILE]...
#tar {A|c|d|r|t|u|x}[GnSkUWOmpsMBiajJzZhPlRvwo] [ARG...]

UNIX 风格写法

1
2
3
4
5
6
7
tar -A [OPTIONS] ARCHIVE ARCHIVE
tar -c [-f ARCHIVE] [OPTIONS] [FILE...]
tar -d [-f ARCHIVE] [OPTIONS] [FILE...]
tar -t [-f ARCHIVE] [OPTIONS] [MEMBER...]
tar -r [-f ARCHIVE] [OPTIONS] [FILE...]
tar -u [-f ARCHIVE] [OPTIONS] [FILE...]
tar -x [-f ARCHIVE] [OPTIONS] [MEMBER...]

GNU 风格写法

1
2
3
4
5
6
7
8
9
10
tar {--catenate|--concatenate} [OPTIONS] ARCHIVE ARCHIVE
tar --create [--file ARCHIVE] [OPTIONS] [FILE...]
tar {--diff|--compare} [--file ARCHIVE] [OPTIONS] [FILE...]
tar --delete [--file ARCHIVE] [OPTIONS] [MEMBER...]
tar --append [-f ARCHIVE] [OPTIONS] [FILE...]
tar --list [-f ARCHIVE] [OPTIONS] [MEMBER...]
tar --test-label [--file ARCHIVE] [OPTIONS] [LABEL...]
tar --update [--file ARCHIVE] [OPTIONS] [FILE...]
tar --update [-f ARCHIVE] [OPTIONS] [FILE...]
tar {--extract|--get} [-f ARCHIVE] [OPTIONS] [MEMBER...]

常用选项

1
2
3
4
5
6
7
8
9
10
11
12
13
#必选项 {A|c|d|r|t|u|x}
-A|--catenate|--concatenate #追加 tar 文件至归档
-c|--create #创建一个新归档
-d|--diff|--compare #找出归档和文件系统的差异
--delete #从归档(非磁带!)中删除
-r|--append #追加文件至归档结尾
-t|--list #列出归档内容
--test-label #测试归档卷标并退出
-u|--update #仅追加比归档中副本更新的文件
-x|--extract|--get #从归档中解出文件

# -f 选项
-f|--file=ARCHIVE #指定压缩包文件,大多数必选

OPTIONS选项

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
#OPTIONS选项 [GnSkUWOmpsMBiajJzZhPlRvwo],这些选项要注意位置

-G|--incremental #处理老式的 GNU 格式的增量备份
-n|--seek #归档可检索
-S|--sparse #高效处理离散文件
-k|--keep-old-files #解包时不覆盖已有的文件
-U|--unlink-first #解压之前先删除文件的链接
-W|--verify #在写入以后尝试校验归档
-O|--to-stdout #解压文件至标准输出
--to-command=COMMAND #将解压的文件通过管道传送至另一个程序
-m|--touch #不要解压文件的修改时间
-p|--preserve-permissions|--same-permissions #保留文件权限信息
-s|--preserve-order|--same-order #成员参数按归档中的文件顺序列出
-M|--multi-volume #创建/列出/解压多卷归档文件
-B|--read-full-records #读取时重新分块(只对 4.2BSD 管道有效)
-i|--ignore-zeros #忽略归档中的零字节块(即文件结尾)
-a|--auto-compress #使用归档后缀名来决定压缩程序
-j|--bzip2 #使用 bzip2 压缩或解压缩
-J|--xz #使用 xz 压缩或解压缩
--lzip|--lzma|--lzop #lzip|xz --format=lzma|lzop
-z|--gzip|--gunzip|--ungzip #通过 gzip 压缩或解压缩
-Z|--compress|--uncompress #通过 compress 压缩或解压缩
-h|--dereference #将软链接指向的目标文件也压缩打包
--hard-dereference #将硬链接指向的目标文件也压缩打包
-P|--absolute-names #不要从文件名中清除引导符‘/’
-l|--check-links #只输出非链接文件的信息
-R|--block-number #每个信息都显示归档内的块数
-v|--verbose #列出文件详细信息
-w|--interactive|--confirmation #操作前手动确认
-o #用老旧的 V7 tar 格式打包或解包

压缩选项

1
2
3
-z                     #相当于gzip压缩工具
-j #相当于bzip2压缩工具
-J #相当于xz压缩工具

其它选项

1
2
3
4
5
6
--show-defaults                     #显示 tar 默认选项
--exclude #排除文件
-C|--directory=DIR #指定目录
-T|--files-from=FILE #从文件中读取要处理的文件
-X|--exclude-from=FILE #从文件中读取要排除的文件
--version #显示版本号
1
2
3
4
5
6
#默认采用相对路径
[root@rocky86 0726]# tar -cf etc.tar /etc
tar: Removing leading `/' from member names

#P保留路径
[root@rocky86 0726]# tar -cPf etc2.tar /etc

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#只打包,不压缩
[root@rocky86 0726]# tar -cvf test.tar f1.txt f2.txt
f1.txt
f2.txt

#递归打包目录
[root@rocky86 0726]# tar -cvf log.tar /var/log

#大小相同
[root@rocky86 0726]# du -sh /var/log/
13M /var/log/

[root@rocky86 0726]# ll -h log.tar
-rw-r--r-- 1 root root 13M Jul 26 15:57 log.tar

范例:只打包目录内的文件,不所括目录本身

1
2
3
4
5
[root@rocky86 ~]# cd /etc/
[root@rocky86 etc]# tar -cf etc.tar *

#先指定目录
[root@rocky86 ~]# tar -C /etc/ -cf etc.tar ./

范例:追加和删除

不支持对压缩文件追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@rocky86 0726]# tar -tvf test.tar
-rw-r--r-- root/root 4453 2022-07-26 15:19 f1.txt
-rw------- root/root 1946847 2022-07-26 14:09 f2.txt

#追加
[root@rocky86 0726]# tar -rf test.tar f3.txt passwd

[root@rocky86 0726]# tar -tvf test.tar
-rw-r--r-- root/root 4453 2022-07-26 15:19 f1.txt
-rw------- root/root 1946847 2022-07-26 14:09 f2.txt
-rw------- root/root 1814952 2022-07-26 14:09 f3.txt
-rw-r--r-- root/root 2858 2022-07-25 22:09 passwd

#删除
[root@rocky86 0726]# tar --delete -vf test.tar f1.txt f2.txt

[root@rocky86 0726]# tar -tvf test.tar
-rw------- root/root 1814952 2022-07-26 14:09 f3.txt
-rw-r--r-- root/root 2858 2022-07-25 22:09 passwd

#将test1.tar 中的文件解出来再打包到 test2.tar 中,test1.tar 中不删除
[root@rocky86 0726]# tar -A test.tar -f test2.tar

范例:列出包内文件

1
2
3
[root@rocky86 0726]# tar -tvf test.tar 
-rw------- root/root 1814952 2022-07-26 14:09 f3.txt
-rw-r--r-- root/root 2858 2022-07-25 22:09 passwd

范例:解包

1
2
3
4
[root@rocky86 0726]# tar -xf log.tar

#指定目录
[root@rocky86 0726]# tar -xf log.tar -C /tmp

范例:打包并压缩

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky86 0726]# tar -zcvf etc.tar.gz /etc/
[root@rocky86 0726]# tar -jcvf etc.tar.bz2 /etc/
[root@rocky86 0726]# tar -Jcvf etc.tar.xz /etc/

root@rocky86 0726]# ll -h etc.tar.*
-rw-r--r-- 1 root root 4.7M Jul 26 16:37 etc.tar.bz2
-rw-r--r-- 1 root root 6.4M Jul 26 16:36 etc.tar.gz
-rw-r--r-- 1 root root 4.0M Jul 26 16:37 etc.tar.xz

[root@rocky86 0726]# tar -xf etc.tar.gz -C /tmp/etc-gz/
[root@rocky86 0726]# tar -xf etc.tar.bz2 -C /tmp/etc-bz2/
[root@rocky86 0726]# tar -xf etc.tar.xz -C /tmp/etc-xz/

范例:从文件中读取要打包的文件

1
2
3
4
5
6
7
[root@rocky86 0726]# cat list.txt 
f1.txt
f2.txt

[root@rocky86 0726]# tar -zcvf x.tar.gz -T list.txt
f1.txt
f2.txt

范例:排除和包含文件

1
2
3
4
5
#指定跳过的文件
[root@rocky86 ~]# tar zcvf /root/a.tgz --exclude=/app/host1 --exclude=/app/host2 /app

#从文件读取
[root@rocky86 ~]# tar zcvf mybackup.tgz -T /root/includefilelist -X /root/excludefilelist

范例:查看默认选项

1
2
[root@rocky86 0726]# tar --show-defaults
--format=gnu -f- -b20 --quoting-style=escape --rmt-command=/etc/rmt --rsh-command=/usr/bin/ssh

split

split 命令可以分割一个文件为多个文件

格式:

1
2
3
4
5
6
7
8
split [OPTION]... [FILE [PREFIX]]

#常用选项
-b|--bytes=SIZE #按大小指定分割单位
-C|--line-bytes=SIZE #同-b,但是在切割时将尽量维持每行的完整性
-d #切割后小文件的后缀用数字表示
-l|--lines=NUMBER #指定行数,按多少行切一个小文件
--verbose #显示过程

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#将test.txt 以6行为单位进行切切割成以 x 为前缀名称的小文件
[root@rocky86 ~]# split -l 6 test.txt

#同上
[root@rocky86 ~]# split -6 test.txt

#以1M大小为单位切割,小文件以数字为后缀,etc.part 开头
[root@rocky86 ~]# split -b 1M etc.tar.gz -d etc.part

#显示过程
[root@rocky86 ~]# split --verbose -b 1M etc.tar.gz -d etc.part

#合并回去
[root@rocky86 ~]# cat etc.part* > etc.tar.gz