文件系统目录结构

1

FHS文件系统

FHS(Filesystem Hierarchy Standard:文件系统层次化标准),是由Linux基金会维护的,帮助发行版 厂商和开发者们使用共同的标准来约定其发行的Linux系统或开发的软件遵守共同的文件和目录标准。

FHS是多数Linux版本采用的文件组织形式,采用树形结构组织文件。FHS定义了系统中每个区域的用 途、所需要的最小构成的文件和目录,同时还给出了例外处理与矛盾处理。

官方网站:https://www.pathname.com/fhs/

文件系统的目录结构

  • 文件和目录被组织成一个单根倒置树结构
  • 文件系统从根目录下开始,用“/”表示
  • 根文件系统(rootfs):root filesystem
  • 标准Linux文件系统(如:ext4),文件名称大小写敏感,例如:MAIL, Mail, mail, mAiL
  • 以 . 开头的文件为隐藏文件
  • 路径分隔的 /
  • 文件名最长255个字节
  • 包括路径在内文件名称最长4095个字节
  • 蓝色–>目录 绿色–>可执行文件 红色–>压缩文件 浅蓝色–>链接文件 灰色–>其他文件
  • 除了斜杠和NUL,所有字符都有效。但使用特殊字符的目录名和文件不推荐使用,有些字符需要用引号来引用
  • 每个文件都有两类相关数据:元数据:metadata,即属性, 数据:data,即文件内容

常见的文件系统目录功能

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
/boot              #引导文件存放目录,内核文件(vmlinuz)、引导加载器(bootloader, grub)都存放于此目录
/bin #所有用户使用的基本命令;不能关联至独立分区,OS启动即会用到的程序
/sbin #管理类的基本命令;不能关联至独立分区,OS启动即会用到的程序
/lib #启动时程序依赖的基本共享库文件以及内核模块文件(/lib/modules)
/lib64 #专用于x86_64系统上的辅助共享库文件存放位置
/etc #配置文件目录
/home/USERNAME #普通用户家目录
/root #管理员的家目录
/media #便携式移动设备挂载点
/mnt #临时文件系统挂载点
/dev #设备文件及特殊文件存储位置, b:block device,随机访问,c:character device,线性访问
/opt #第三方应用程序的安装位置
/srv #系统上运行的服务用到的数据
/tmp #临时文件存储位置
/usr #universal shared, read-only data
/usr/bin #保证系统拥有完整功能而提供的应用程序
/usr/sbin #同上
/usr/lib #32位使用
/usr/lib64 #只存在64位系统
/usr/include #C程序的头文件(header files)
/usr/share #结构化独立的数据,例如doc, man等
/var #variable data files,可变数据目录
/var/cache #应用程序缓存数据目录
/var/lib #应用程序状态信息数据
/var/local #专用于为/usr/local下的应用程序存储可变数据
/var/lock #锁文件
/var/log #日志目录及文件
/var/opt #专用于为/opt下的应用程序存储可变数据
/var/run #运行中的进程相关数据,通常用于存储进程pid文件
/var/spool #应用程序数据池
/var/tmp #保存系统两次重启之间产生的临时数据
/proc #用于输出内核与进程信息相关的虚拟文件系统
/sys #用于输出当前系统上硬件设备相关信息虚拟文件系统
/selinux #security enhanced Linux,selinux相关的安全策略等信息的存储位置

应用程序的组成部分

不同类型文件常用的目录

文件类型 常用目录
二进制文件 /bin,/sbin,/usr/bin,/usr/sbin,/usr/local/bin
/usr/local/sbin
库文件 /lib,/lib64,/usr/lib64,/usr/local/lib,/usr/local/lib64
配置文件 /etc,/etc/DIRECTORY,/usr/local/etc
帮助文件 /usr/share/man,/usr/share/doc,/usr/local/share/man
/usr/local/share/doc

新版本目录结构变化

  • /bin 和 /usr/bin
  • /sbin 和 /usr/sbin
  • /lib 和/usr/lib
  • /lib64 和 /usr/lib64

范例:

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@centos8 ~]#ls /bin /sbin /lib /lib64 -ld
lrwxrwxrwx. 1 root root 7 May 11 2019 /bin -> usr/bin
lrwxrwxrwx. 1 root root 7 May 11 2019 /lib -> usr/lib
lrwxrwxrwx. 1 root root 9 May 11 2019 /lib64 -> usr/lib64
lrwxrwxrwx. 1 root root 8 May 11 2019 /sbin -> usr/sbin


[root@centos6 ~]#ls /bin /sbin /lib /lib64 -ld
dr-xr-xr-x. 2 root root 4096 Mar 20 09:14 /bin
dr-xr-xr-x. 11 root root 4096 Dec 12 2018 /lib
dr-xr-xr-x. 9 root root 12288 Mar 20 09:13 /lib64
dr-xr-xr-x. 2 root root 12288 Mar 20 09:14 /sbin


[root@ubuntu2004 ~]#ls /bin /sbin /lib /lib64 -ld
lrwxrwxrwx 1 root root 7 Aug 24 2021 /bin -> usr/bin
lrwxrwxrwx 1 root root 7 Aug 24 2021 /lib -> usr/lib
lrwxrwxrwx 1 root root 9 Aug 24 2021 /lib64 -> usr/lib64
lrwxrwxrwx 1 root root 8 Aug 24 2021 /sbin -> usr/sbin


[root@ubuntu1804 ~]#ll /bin /usr/bin -d
drwxr-xr-x 2 root root 4096 Jan 12 18:41 /bin/
drwxr-xr-x 2 root root 24576 Jan 12 18:42 /usr/bin/

Linux下的文件类型

linux 系统中的文件类型标识符

文件类型 标识符 说明
普通文件 -
目录文件 d directory
符号链接文件 l link
块设备文件 b block
字符设备文件 c character
管道文件 p pipe
套接字文件 s socket

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@centos7 ~]#ls -l /run/
total 52
drwxr-xr-x 2 root root 100 Dec 9 20:41 abrt
-rw------- 1 root root 11 Dec 9 20:41 alsactl.pid
-rw-r--r-- 1 root root 5 Dec 9 20:41 atd.pid
-rw-r--r-- 1 root root 4 Dec 9 20:41 auditd.pid
prw------- 1 root root 0 Dec 9 20:41 autofs.fifo-misc
prw------- 1 root root 0 Dec 9 20:41 autofs.fifo-net
drwxr-xr-x 2 avahi avahi 80 Dec 9 20:41 avahi-daemon
drwxr-xr-x 2 root root 40 Dec 9 20:41 certmonger
drwxr-x--- 2 chrony chrony 80 Dec 9 20:41 chrony
drwxr-xr-x 2 root root 40 Dec 9 20:41 console
-rw-r--r-- 1 root root 5 Dec 9 20:41 crond.pid
---------- 1 root root 0 Dec 9 20:41 cron.reboot

linux 系统中的文件类型颜色标识

linux 系统中,每种颜色,都有对应的含义,可以根据文件在终端中显示的颜色,来判断是什么类型的文件

颜色与文件类型对应关系,由配置文件定义,可更改(此处的文件类型,可以理解为文件格式)

文件类型(格式) 颜色
普通文件 白色
目录文件 蓝色
符号链接文件 浅蓝色
块设备文件 黄色
字符设备文件 黄色
管道文件 青黄色
套接字文件 粉红色
图片文件 粉红色
压缩文件或文件包 红色
其他文件 灰色

管道文件

所谓管道,是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称 pipe 文件。

2

套接字文件

Socket本身有“插座”的意思,在Unix/Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。

3

文件操作命令

显示当前工作目录

每个shell和系统进程都有一个当前的工作目录 CWD:current work directory

显示当前shell CWD的绝对路径

pwd命令: printing working directory

1
2
3
4
pwd [-LP]
#常用选项
-P #显示真实物理路径
-L #显示链接路径(默认)

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@centos8 ~]#pwd
/root

[root@centos8 ~]#cd /data
[root@centos8 data]#pwd
/data

[root@rocky8 ~]# ll /bin
lrwxrwxrwx. 1 root root 7 Oct 11 2021 /bin -> usr/bin

[root@rocky8 ~]# cd /bin
[root@rocky8 bin]# pwd
/bin

[root@rocky8 bin]# pwd -P
/usr/bin

绝对和相对路径

描述一个文件位置有两种方式

绝对路径

  1. 以正斜杠/ 即根目录开始
  2. 描述完整的文件的位置路径
  3. 可用于任何想指定一个文件名的时候

相对路径

  1. 不以斜线开始,而是以当前所在的位置开始
  2. 一般情况下,是指相对于当前工作目录的路径,特殊场景下,是相对于某目录的位置
  3. 可以作为一个简短的形式指定一个文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#走绝对路径
[root@rocky86 ~]# pwd
/root

[root@rocky86 ~]# cd /etc/sysconfig/


#走相对路径
[root@rocky86 sysconfig]# pwd
/etc/sysconfig

[root@rocky86 sysconfig]# cd network-scripts/
[root@rocky86 network-scripts]# pwd
/etc/sysconfig/network-scripts

[root@rocky86 network-scripts]# cd ../../../root/
[root@rocky86 ~]# pwd
/root

基名 & 目录名

基名:basename,只取文件名而不要路径

目录名:dirname,只取路径,不要文件名

范例:

1
2
3
4
5
6
7
8
9
10
11
[root@centos8 bin]#basename /etc/sysconfig/network
network

[root@centos8 bin]#dirname /etc/sysconfig/network
/etc/sysconfig

[root@centos8 ~]#dirname /etc/sysconfig/network-scripts/ifcfg-eth0
/etc/sysconfig/network-scripts

[root@centos8 ~]#basename /etc/sysconfig/network-scripts/ifcfg-eth0
ifcfg-eth0

范例:

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky86 ~]# basename http://nginx.org/download/nginx-1.18.0.tar.gz
nginx-1.18.0.tar.gz

[root@rocky86 ~]# basename http://nginx.org/download/nginx-1.18.0.tar.gz.tar.gz
nginx-1.18.0.tar.gz.tar.gz

# -s删除后缀
[root@rocky86 ~]# basename -s .tar.gz http://nginx.org/download/nginx-1.18.0.tar.gz
nginx-1.18.0

[root@rocky86 ~]# basename -s .tar.gz http://nginx.org/download/nginx-1.18.0.tar.gz.tar.gz
nginx-1.18.0.tar.gz

范例:

1
2
3
[root@rocky86 ~]# url=http://nginx.org/download/nginx-1.18.0.tar.gz
[root@rocky86 ~]# wget $url
[root@rocky86 ~]# tar xf `basename $url`

更改目录

1
2
3
4
5
6
7
8
9
10
cd [-L|[-P [-e]] [-@]] [dir]

#常用选项
-L #切换至链接目录,默认选项
-P #切换至真实目录,而非链接目录

cd .. #切换至父目录
cd - #切换到上一个目录
cd | cd ~ #切换至当前用户家目录
cd ~username #切换至指定用户家目录

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@centos8 ~]#cd /etc/sysconfig
[root@centos8 sysconfig]#pwd
/etc/sysconfig

[root@centos8 sysconfig]#cd ../../data
[root@centos8 data]#pwd
/data

[root@centos8 data]#cd /bin
[root@centos8 bin]#pwd
/bin

[root@centos8 bin]#cd -P /bin
[root@centos8 bin]#pwd
/usr/bin

相关环境变量

1
2
3
4
5
6
7
8
9
10
11
$PWD          #当前目录
$OLDPWD #上一次目录

[root@rocky86 boot]# echo $PWD $OLDPWD
/boot /var

[root@rocky86 boot]# cd -
/var

[root@rocky86 var]# echo $PWD $OLDPWD
/var /boot

列出目录内容

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

#常用选项

-a|--all #包含隐藏文件
-l #显示额外的信息
-R|--recursive #目录递归
-d|--directory #仅显示当前目录
-1 #数字1,文件分行显示
-S #按从大到小排序
-t #按mtime排序,时间新的靠前
-u #配合-t选项,显示并按atime从新到旧排序
-U #按目录存放顺序显示
-X #按文件后缀排序
-F|--classify #对不同类型文件显示时附加不同的符号:*/=>@|

说明:

  1. ls 查看不同后缀文件时的颜色由 /etc/DIR_COLORS 和@LS_COLORS变量定义
  2. ls -l 看到文件的大小,不一定是实际文件真正占用空间的大小
  3. ll 是 ls命令的一个别名,在centos 和 ubuntu 系统中,该别名的参数不一样
1
2
3
4
5
[root@rocky86 ~]# alias ll
alias ll='ls -l --color=auto'

root@ubuntu20:~# alias ll
alias ll='ls -alF'

范例:

1
2
3
4
[root@centos8 ~]#vim /etc/DIR_COLORS
.jpg 01;31 #修改此行
[root@centos8 ~]#exit
[root@centos8 ~]#echo $LS_COLORS

查看文件状态 stat

一个文件有两部份信息:元数据和具体内容

查看文件元数据

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

#常用选项

-t|--terse #使用简洁格式显示
-f|--file-system #显示相关的文件系统信息,所谓文件系统,对应的就是windows下面的硬盘分区
-c|--format #使用特定格式输出

每个文件有三个时间戳属性

属性 说明
atime access time 访问时间,即读取文件内容时间,
此字段值会延时更新,以降低IO负载
mtime modify time 修改内容的时间
ctime change time 元数据发生改变的时间
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
#查看文件元数据
[root@rocky8 ~]# stat /etc/fstab
File: /etc/fstab
Size: 655 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 268568707 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:etc_t:s0
Access: 2024-04-26 21:35:28.670048634 +0800
Modify: 2024-04-24 15:23:46.540624845 +0800
Change: 2024-04-24 15:27:00.584639230 +0800
Birth: 2024-04-24 15:23:46.540624845 +0800


#目录也是一个文件
[root@rocky8 ~]# stat /boot/
File: /boot/
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 801h/2049d Inode: 128 Links: 5
Access: (0555/dr-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:boot_t:s0
Access: 2024-04-24 15:26:19.568636898 +0800
Modify: 2024-04-24 16:07:59.307086248 +0800
Change: 2024-04-24 16:07:59.307086248 +0800
Birth: 2024-04-24 15:23:43.025759000 +0800


#查看文件所在分区的信息
[root@rocky8 ~]# stat -f /etc/fstab
File: "/etc/fstab"
ID: fd0000000000 Namelen: 255 Type: xfs
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 34062080 Free: 33422263 Available: 33422263
Inodes: Total: 68157440 Free: 68121720


#权限-inode-文件名
[root@rocky8 ~]# stat -c "%a-%i-%n" /etc/fstab
644-268568707-/etc/fstab

确定文件类型

文件可以包含多种类型的数据,使用file命令检查文件的类型,然后确定适当的打开命令或应用程序使用

格式:

1
2
3
4
5
6
7
8
file [options] <filename>...

#常用选项

-b|--brief #只显示结果,不显示文件名
-f|--files-from FILE #从指定文件中获取要处理的文件名
-F|--separator STRING #指定分割符
-L|--dereference #跟随软链接

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@rocky8 ~]# file /usr/lib/dracut/dracut-init.sh
/usr/lib/dracut/dracut-init.sh: Bourne-Again shell script, ASCII text executable

[root@rocky8 ~]# file -b /usr/lib/dracut/dracut-init.sh
Bourne-Again shell script, ASCII text executable

[root@rocky8 ~]# cat list.txt
/etc/
/bin
/etc/issue

[root@rocky8 ~]# file -f list.txt
/etc/: directory
/bin: symbolic link to usr/bin
/etc/issue: ASCII text

范例:windows的文本格式和Linux的文本格式的区别

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
[root@rocky8 ~]# cat linux.txt 
a
b
c

[root@rocky8 ~]# cat win.txt
a
b
c[root@rocky8 ~]# file win.txt linux.txt
win.txt: ASCII text, with CRLF line terminators
linux.txt: ASCII text

[root@rocky8 ~]# hexdump -C linux.txt
00000000 61 0a 62 0a 63 0a |a.b.c.|
00000006

[root@rocky8 ~]# hexdump -C win.txt
00000000 61 0d 0a 62 0d 0a 63 |a..b..c|
00000007

#安装转换工具
[root@rocky8 ~]# dnf -y install dos2unix

#将Windows的文本格式转换成的Linux文本格式
[root@rocky8 ~]# dos2unix win.txt
dos2unix: converting file win.txt to Unix format...

[root@rocky8 ~]# file win.txt
win.txt: ASCII text

#将Linux的文本格式转换成Windows的文本格式
[root@rocky8 ~]# unix2dos win.txt
unix2dos: converting file win.txt to DOS format...

[root@rocky8 ~]# file win.txt
win.txt: ASCII text, with CRLF line terminators

范例:转换文件字符集编码

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@rocky8 ~]#iconv -l

#windows7上文本默认的编码ANSI(GB2312)

[root@centos8 data]#file windows.txt
windows.txt: ISO-8859 text, with no line terminators

[root@centos8 data]#echo $LANG
en_US.UTF-8

#默认在linux无法正常显示文本内容
[root@centos8 data]#cat windows.txt
▒▒▒▒▒▒[root@centos8 data]#

#将windows7上文本默认的编码ANSI(GB2312)转换成UTF-8
[root@centos8 data]#iconv -f gb2312 windows.txt -o windows1.txt

[root@centos8 data]#cat windows1.txt
马哥教育[root@centos8 data]#ll windows1.txt
-rw-r--r-- 1 root root 12 Mar 23 10:13 windows1.txt

[root@centos8 data]#file windows1.txt
windows1.txt: UTF-8 Unicode text, with no line terminators

#将UTF-8转换成windows10上文本默认的编码ANSI(GB2312)
[root@centos8 data]#iconv -f utf8 -t gb2312 windows1.txt -o windows2.txt

[root@centos8 data]#file windows2.txt
windows2.txt: ISO-8859 text, with no line terminators

文件通配符模式 wildcard pattern

文件通配符可以用来匹配符合条件的多个文件,方便批量管理文件

通配符采有特定的符号,表示特定的含义,此特符号称为元 meta 字符

常见的通配符如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
*           #匹配零个或多个字符,但不匹配 "." 开头的文件,即隐藏文件
? #匹配任何单个字符,一个汉字也算一个字符
~ #当前用户家目录
. #当前工作目录
~+ #当前工作目录
~- #前一个工作目录
~mage #用户mage家目录
[0-9] #匹配数字范围
[a-z] #一个字母
[A-Z] #一个字母
[wang] #匹配列表中的任何的一个字符
[^wang] #匹配列表中的所有字符以外的字符
[^a-z] #匹配列表中的所有字符以外的字符

另外还有在Linux系统中预定义的字符类表示法如下:man 7 glob

1
2
3
4
5
6
7
8
9
10
11
12
[:digit:]     #任意数字,相当于0-9
[:lower:] #任意小写字母,表示 a-z
[:upper:] #任意大写字母,表示 A-Z
[:alpha:] #任意大小写字母
[:alnum:] #任意数字或字母
[:blank:] #水平空白字符
[:space:] #水平或垂直空白字符
[:punct:] #标点符号
[:print:] #可打印字符
[:cntrl:] #控制(非打印)字符
[:graph:] #图形字符
[:xdigit:] #十六进制字符

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#匹配以a开头的
[root@rocky8 ~]# ll a*

#匹配包含a的
[root@rocky86 ~]# ll *a*

#匹配任意单字符文件名的文件
[root@rocky8 ~]# ll ?
-rw-r--r-- 1 root root 0 Jul 10 22:34 a
-rw-r--r-- 1 root root 0 Jul 10 22:34 马

#匹配两个字符
[root@rocky86 ~]# ll ??
-rw-r--r-- 1 root root 0 Jul 10 22:34 ab
-rw-r--r-- 1 root root 0 Jul 10 22:34 马g
-rw-r--r-- 1 root root 0 Jul 10 22:34 马哥

范例:

1
2
3
4
5
6
[root@rocky86 ~]# echo $OLDPWD
/data

#查看前一个目录下的linux.txt
[root@rocky86 ~]# ll ~-/linux.txt
-rw-r--r-- 1 root root 6 Mar 23 09:48 /data/linux.txt

范例: [ ] 和 { }

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
[root@rocky86 ~]# ll f{1..5}
ls: cannot access 'f1': No such file or directory
ls: cannot access 'f2': No such file or directory
-rw-r--r-- 1 root root 0 Nov 7 09:34 f3
-rw-r--r-- 1 root root 0 Nov 7 09:34 f4
-rw-r--r-- 1 root root 0 Nov 7 09:34 f5


[root@rocky86 ~]# ll f[1-5]
-rw-r--r-- 1 root root 0 Nov 7 09:34 f3
-rw-r--r-- 1 root root 0 Nov 7 09:34 f4
-rw-r--r-- 1 root root 0 Nov 7 09:34 f5


[root@rocky86 ~]# ll f[a-c]
-rw-r--r-- 1 root root 0 Nov 7 09:46 fa
-rw-r--r-- 1 root root 0 Nov 7 09:46 fA
-rw-r--r-- 1 root root 0 Nov 7 09:46 fb
-rw-r--r-- 1 root root 0 Nov 7 09:46 fB
-rw-r--r-- 1 root root 0 Nov 7 09:46 fc


[root@rocky86 ~]# ll f{a..c}
-rw-r--r-- 1 root root 0 Nov 7 09:46 fa
-rw-r--r-- 1 root root 0 Nov 7 09:46 fb
-rw-r--r-- 1 root root 0 Nov 7 09:46 fc


#[a-z] 表示小a 到小z,大A 到大Z aAbBcC ... zZ
[root@rocky86 ~]# ls test-[a-d].txt
test-a.txt test-A.txt test-b.txt test-B.txt test-c.txt test-C.txt test-d.txt

范例:

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
[root@rocky86 ~]# touch file{a..z}.txt file{A..Z}.txt file{0..9}.txt

[root@rocky86 ~]# ll file{0..9}.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file0.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file1.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file2.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file3.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file4.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file5.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file6.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file7.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file8.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file9.txt


[root@rocky86 ~]# ll file[0-9].txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file0.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file1.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file2.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file3.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file4.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file5.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file6.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file7.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file8.txt
-rw-r--r-- 1 root root 0 Mar 23 10:46 file9.txt


[root@rocky86 ~]# ls file[a-c].txt
filea.txt fileA.txt fileb.txt fileB.txt filec.txt

[root@rocky86 ~]# ls file[C-E].txt
fileC.txt filed.txt fileD.txt filee.txt fileE.txt

[root@rocky86 ~]# ls file[wang].txt
filea.txt fileg.txt filen.txt filew.txt

[root@rocky86 ~]# ls file[^wang].txt

范例:

1
2
3
4
5
6
7
8
9
10
11
#匹配中括号中的任意一个字符
[root@rocky86 ~]# ls file[:lower:].txt
filee.txt filel.txt fileo.txt filer.txt filew.txt


#匹配小写字母
[root@rocky86 ~]# ls file[[:lower:]].txt
filea.txt filed.txt fileg.txt filej.txt filem.txt filep.txt files.txt filev.txt
filey.txt fileb.txt filee.txt fileh.txt filek.txt filen.txt fileq.txt filet.txt
filew.txt filez.txt filec.txt filef.txt filei.txt filel.txt fileo.txt filer.txt
fileu.txt filex.txt

范例:比较有无*的功能区别

1
2
3
4
5
ls *         #等同于 ls 列出当前目录内容,不包括 . 和 ..
ls -a * #等同于 ls 列出当前目录内容,不包括 . 和 ..
ls -a #列出当前目录所有内容,包括 . 和 ..
ls .* #列出当前目录和上级目录的内容, .* 包括 .. 也就是上级目录
ls -d .* #只显示当前目录的内容,有预定的别名 l.

范例:

1
2
[root@rocky86 ~]# ls -d /etc/*/
[root@rocky86 ~]# l.

范例:

1
2
3
4
5
6
7
8
9
[root@rocky86 ~]# touch file*.log

[root@rocky86 ~]# touch file1.log

[root@rocky86 ~]# ls file*.log
file1.log 'file*.log'

[root@rocky86 ~]# ls 'file*.log'
'file*.log'

创建空文件和刷新时间

touch命令可以用来创建空文件或刷新文件的时间

格式:

1
2
3
4
5
6
7
8
9
10
11
12
touch [OPTION]... FILE...

#常用选项

-a #改变atime,ctime
-m #改变mtime,ctime
-h|--no-dereference #touch链接文件时,默认是操作其指向的目标文件,此选项表示操作链接文件本身
-r|--reference #使用某个文件的更新时间和修改时间作为当前文件的更新时间和修改时间
-d|--date #指定修改时间和访问时间,而不是采用当前系统时间
-t [[CC]YY]MMDDhhmm[.ss] # --time=WORD
--time=STRING #指定修改项 access|atime 等同于 -a, modify|mtime 等同于 -m
-c|--no-create #如果文件不存在,不创建

范例:

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
64
65
66
67
68
69
70
[root@rocky8 ~]# touch f1.txt

[root@rocky8 ~]# ll f1.txt
-rw-r--r--. 1 root root 0 Apr 28 16:09 f1.txt

[root@rocky8 ~]# ll /etc/issue
-rw-r--r--. 1 root root 23 Oct 9 2021 /etc/issue

[root@rocky8 ~]# touch /etc/issue

[root@rocky8 ~]# ll /etc/issue
-rw-r--r--. 1 root root 23 Apr 28 16:09 /etc/issue

[root@rocky8 ~]# stat /etc/issue
File: /etc/issue
Size: 23 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 268597004 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:etc_t:s0
Access: 2024-04-28 16:09:42.549239569 +0800
Modify: 2024-04-28 16:09:42.549239569 +0800
Change: 2024-04-28 16:09:42.549239569 +0800
Birth: 2024-04-24 15:23:58.278625794 +0800


[root@rocky8 ~]# date
Sun Apr 28 16:10:13 CST 2024

# -1 day代表减一天
[root@rocky8 ~]# touch `date -d "-1 day" +%F_%T`.log

[root@rocky8 ~]# ls
2024-04-27_16:10:55.log anaconda-ks.cfg f1.txt

# 1 year代表加一年
[root@rocky8 ~]# touch $(date -d "1 year" +%F_%T).log

[root@rocky8 ~]# ls
2024-04-27_16:10:55.log 2025-04-28_16:16:02.log anaconda-ks.cfg f1.txt

[root@rocky8 ~]# touch -d "2022-05-05 05:05:05" abc

[root@rocky8 ~]# stat abc
File: abc
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd00h/64768d Inode: 402660596 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2022-05-05 05:05:05.000000000 +0800
Modify: 2022-05-05 05:05:05.000000000 +0800
Change: 2024-04-28 16:18:32.601257694 +0800
Birth: 2024-04-28 16:18:32.601257694 +0800


#将abc 的时间赋值给abcd
[root@rocky8 ~]# touch -r abc abcd

#将abc 时间设置为7月8日9时10分
[root@rocky8 ~]# touch -t 07080910 abc

[root@rocky8 ~]# stat abc
File: abc
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd00h/64768d Inode: 402660596 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2024-07-08 09:10:00.000000000 +0800
Modify: 2024-07-08 09:10:00.000000000 +0800
Change: 2024-04-28 16:20:46.552262274 +0800
Birth: 2024-04-28 16:18:32.601257694 +0800

复制文件和目录

利用 cp(copy)命令可以实现文件或目录的复制

格式:

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
cp [OPTION]... [-T] SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...


#常用选项

-i|--interactive #如果目标文件己存在,则提示是否覆盖
-n|--no-clobber #如果目标文件己存在,则跳过此文件复制
-R|-r|--recursive #递归复制,可用于目录的复制
-a|--archive #保留所有属性 相当于 dpR 选项组合
-s|--symbolic-link #不复制文件,而是创建链接
-p #同时复制访问时间,修改时间,权限等属性,同 --preserve=mode,ownership,timestamps
--preserve[=ATTR_LIST] #选择属性,默认为 mode,ownership,timestamps
-u|--update #当源文件比目标文件新时,才执行复制操作
-v|--verbose #显示复制过程
-b #先备份再覆盖
--backup=numbered #目标存在,覆盖前先备份加数字后缀,形式为 filename.~#~ ,可以保留多个版本

mode #权限
ownership #属主属组
timestamp #时间戳
links #保留链接
xattr #保留自定义属性
context #保留selinux属性
all #所有属性
源/目标 不存在 存在且为文件 存在且目录
一个文件 新建DEST,并将SRC中
内容填充至DEST中
将SRC中的内容覆盖至 DEST中
注意数据丢失风 险!
建议用 –i 选项
在DEST下新建与原文件同名 的文件,
并将SRC中内容填 充至新文件中
多个文件 提示错误 提示错误 在DEST下新建与原文件同名 的文件,
并将原文件内容复 制进新文件中
目录须使
用-r选项
创建指定DEST同名目 录,
复制SRC目录中所 有文件至DEST下
提示错误 在DEST下新建与原目录同名 的目录,
并将SRC中内容复 制至新目录中

范例:

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
[root@rocky86 ~]# cp ~wang/issue /data/issue_wang.bak
-rw-r--r--. 1 root root 86 Dec 13 16:21 /data/issue_wang.bak
-rw-r--r--. 1 wang wang 86 Dec 13 16:18 /home/wang/issue


#保留属主属组,时间戳
[root@rocky86 ~]# cp -p ~wang/issue /data/issue_wang2.bak
[root@rocky86 ~]# ll ~wang/issue /data/issue_wang2.bak
-rw-r--r--. 1 wang wang 86 Dec 13 16:18 /data/issue_wang2.bak
-rw-r--r--. 1 wang wang 86 Dec 13 16:18 /home/wang/issue


#cp 整个目录
[root@rocky86 ~]# cp /etc/sysconfig/ /data/
cp: -r not specified; omitting directory '/etc/sysconfig/'

[root@rocky86 ~]# cp -r /etc/sysconfig/ /data/

[root@rocky86 ~]# ll /data
total 12
-rw-r--r--. 1 root root 0 Dec 13 16:11 2019-12-12_16:11:48.log
-rw-r--r--. 1 root root 0 Dec 13 16:13 2020-12-13_16:13:11.log
-rw-r--r--. 1 wang wang 86 Dec 13 16:18 issue_wang2.bak
-rw-r--r--. 1 root root 86 Dec 13 16:21 issue_wang.bak
drwxr-xr-x. 7 root root 4096 Dec 13 16:23 sysconfig

[root@rocky86 ~]# cp -r /etc/sysconfig/ /data/sysconfig_bak

[root@rocky86 ~]# ll /data
total 16
-rw-r--r--. 1 root root 0 Dec 13 16:11 2019-12-12_16:11:48.log
-rw-r--r--. 1 root root 0 Dec 13 16:13 2020-12-13_16:13:11.log
-rw-r--r--. 1 wang wang 86 Dec 13 16:18 issue_wang2.bak
-rw-r--r--. 1 root root 86 Dec 13 16:21 issue_wang.bak
drwxr-xr-x. 7 root root 4096 Dec 13 16:23 sysconfig
drwxr-xr-x. 7 root root 4096 Dec 13 16:24 sysconfig_bak

范例:复制时如果覆盖先备份再覆盖

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
[root@rocky86 ~]# cp -b /etc/motd /data/issue
cp: overwrite '/data/issue'? y

[16:33:09 root@centos8 ~]#ll /data
total 8
-rw-r--r--. 1 root root 1 Dec 13 16:33 issue
-rw-r--r--. 1 root root 2610 Dec 13 16:32 issue~


#保留多版本备份
[16:33:56 root@centos8 ~]#cp --backup=numbered /etc/fstab /data/issue
cp: overwrite '/data/issue'? y

[16:34:32 root@centos8 ~]#cp --backup=numbered /etc/shadow /data/issue
cp: overwrite '/data/issue'? y

[16:34:41 root@centos8 ~]#cp --backup=numbered /etc/os-release /data/issue
cp: overwrite '/data/issue'? y

[16:34:48 root@centos8 ~]#ll /data
total 20
-rw-r--r--. 1 root root 420 Dec 13 16:34 issue
-rw-r--r--. 1 root root 1 Dec 13 16:33 issue~
-rw-r--r--. 1 root root 709 Dec 13 16:33 issue.~1~
-rw-r--r--. 1 root root 709 Dec 13 16:34 issue.~2~
----------. 1 root root 1349 Dec 13 16:34 issue.~3~

范例:特殊文件复制

1
2
#不能直接cp ,要加 a 选项
[root@centos8 ~]#cp /dev/zero{,.bak}

移动和重命名文件

mv 命令可以实现文件或目录的移动和改名

同一分区移动数据,速度很快:数据位置没有变化

不同分区移动数据,速度相对慢:数据位置发生了变化

格式:

1
2
3
4
5
6
7
8
9
10
mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE...

#常用选项
-b #如果目标存在,则先备份
-n|--no-clobber #如果目标文件己存在,则跳过此文件移动
-i|--interactive #如果目标文件己存在,则提示是否覆盖
-u|--update #当源文件比目标文件新时,才执行移动操作
-v|--verbose #显示移动过程

示例:

1
2
3
4
5
6
7
8
9
10
11
#移动前备份
[root@rocky86 ~]# mv -b a a1

#移动多个文件到目录
[root@rocky86 ~]# mv a b c d abcd/

#将 abc目录放入 abcd 目录中,如果 abcd 目录不存在,则将 abc 目录改名为 abcd 目录
[root@rocky86 ~]# mv abc/ abcd

#将 abc 目录下所有内容移动到当前目录
[root@rocky86 ~]# mv abc/* .

利用 rename 可以批量修改文件名

格式:

1
2
3
4
5
6
7
rename [options] <expression> <replacement> <file>...

#常用选项
-v|--verbose #显示过程
-s|--symlink #如果目标是链接文件,则是重命名其指向
-n|--no-act #不做任何改变
-o|--no-overwrite #不覆盖己存在文件

范例:

1
2
3
4
5
6
7
8
9
10
11
#为所有的f开头包含conf的文件加上.bak后缀
[root@rocky86 ~]# rename 'conf' 'conf.bak' f*

#去掉所有的bak后缀
[root@rocky86 ~]# rename '.bak' '' *.bak

#将当前目录下 以.txt结尾的文件,批量改名成 .log结尾 -v显示过程
[root@rocky86 ~]# rename -v txt log *.txt

#把软连接 abc.link 指向的文件由 abc 改成 xyz
[root@rocky86 ~]# rename -s abc xyz abc.link

删除文件

使用 rm 命令可以删除文件和目录

注意:此命令非常危险,慎重使用,建议使用 mv 代替 rm

格式:

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

#常用选项
-i #删除前确认
-f|--force #不确认直接删除
-r|-R|--recursive #递归删除
-d|--dir #删除空目录
--no-preserve-root #强删根目录

范例:

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky86 ~]# rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe

#删除根下所有内容
[root@rocky86 ~]# rm -rf /*

#删除所有以a开头的文件
[root@rocky86 ~]# rm -f a*

#删除当前目录下所有内容
[root@rocky86 ~]# rm -f *

范例:删除特殊文件

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 0711]# ls
-f

#删不掉
[root@rocky86 0711]# rm -f
[root@rocky86 0711]# ls
-f

#删不掉
[root@rocky86 0711]# rm -rf -f
[root@rocky86 0711]# ls
-f

#删不掉
[root@rocky86 0711]# rm -rf *
[root@rocky86 0711]# ls
-f

[root@rocky86 0711]# rm -rf ./-f
[root@rocky86 0711]# ls

[root@rocky86 0711]# rm -- -f
[root@rocky86 0711]# ls

[root@rocky86 ~]# touch '~'
[root@rocky86 ~]# ls
'~'

[root@rocky86 ~]# rm -f ~
rm: cannot remove '/root': Is a directory

[root@rocky86 ~]# rm -- ~
rm: cannot remove '/root': Is a directory

[root@rocky86 ~]# rm -f ./~

范例:避免误删除,定义别名

1
2
# mv -t 把所有指定的资源移动到/tmp下
[root@rocky86 ~]# alias rm='mv -t /tmp'

目录操作

显示目录树 tree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
tree [-acdfghilnpqrstuvxACDFJQNSUX] [-H baseHREF] [-T title ]

#常用选项
-a #显示所有,包括隐藏目录和文件
-d #只显示目录
-f #显示所有内容的完整路径
-F #在执行文件,目录,Socket,符号链接,管道文件,各自加上"*","/","=","@","|"号
-g #显示文件属组,没找到组名,以gid代替
-u #显示文件属主,没找到用户名,以uid代替
-p #显示内容权限
-s #显示内容大小
-i #不以层级结构显示
-n #不显示颜色
-t #显示时用修改时间排序
-r #以默认显示顺序的反向规则显示,默认以数字,首字母的顺序规则来显示
-o filename #将显示的内容输出到指定文件中
-L n #只显示n层目录
-D #显示内容修改时间
-C #显示色彩

范例:

1
2
3
4
5
6
7
#显示当前目录的树
[root@rocky86 ~]# tree

[root@rocky86 ~]# tree dir1/

#仅显示两层目录
[root@rocky86 ~]# tree -d -L 2 /

创建目录 mkdir

1
2
3
4
5
6
mkdir [OPTION]... DIRECTORY...

#常用选项
-m|--mode #目录权限属性
-p|--parents #如果要创建的目录父级目录不存在,则一起创建,是递归的意思
-v|--verbose #显示创建过程

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@rocky86 ~]# mkdir dira

#指定权限
[root@rocky86 ~]# mkdir -m=777 dirb

#递归创建
[root@rocky86 ~]# mkdir -pv dirx/diry/dirz
mkdir: created directory 'dirx'
mkdir: created directory 'dirx/diry'
mkdir: created directory 'dirx/diry/dirz'

[root@rocky86 ~]# tree dirx
dirx
└── diry
└── dirz

2 directories, 0 files

删除空目录 rmdir

rmdir只能删除空目录,如果想删除非空目录,可以使用rm -r 命令,递归删除目录树

1
2
3
4
5
6
rmdir [OPTION]... DIRECTORY...

#常用选项
--ignore-fail-on-non-empty #忽略非空错误提示
-p|--parents #连着父目录一起删除
-v|--verbose #显示删除过程

范例:从外层开始创建,从里层开始删除

1
2
3
4
5
6
7
8
9
10
11
[root@rocky86 ~]# mkdir -pv a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'

[root@rocky86 ~]# rmdir -pv a/b/c/d
rmdir: removing directory, 'a/b/c/d'
rmdir: removing directory, 'a/b/c'
rmdir: removing directory, 'a/b'
rmdir: removing directory, 'a'

练习

  1. 如何创建/testdir/dir1/x, /testdir/dir1/y, /testdir/dir1/x/a, /testdir/dir1/x/b, /testdir/dir1/y/a, /testdir/dir1/y/b
  2. 如何创建/testdir/dir2/x, /testdir/dir2/y, /testdir/dir2/x/a, /testdir/dir2/x/b
  3. 如何创建/testdir/dir3, /testdir/dir4, /testdir/dir5, /testdir/dir5/dir6, /testdir/dir5/dir7
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
1.
[root@rocky8 ~]# mkdir -pv /testdir/dir1/{x,y}/{a,b}
mkdir: created directory '/testdir'
mkdir: created directory '/testdir/dir1'
mkdir: created directory '/testdir/dir1/x'
mkdir: created directory '/testdir/dir1/x/a'
mkdir: created directory '/testdir/dir1/x/b'
mkdir: created directory '/testdir/dir1/y'
mkdir: created directory '/testdir/dir1/y/a'
mkdir: created directory '/testdir/dir1/y/b'

2.
[root@rocky8 ~]# mkdir -pv /testdir/dir2/{x/{a,b},y}
mkdir: created directory '/testdir/dir2'
mkdir: created directory '/testdir/dir2/x'
mkdir: created directory '/testdir/dir2/x/a'
mkdir: created directory '/testdir/dir2/x/b'
mkdir: created directory '/testdir/dir2/y'

3.
[root@rocky8 ~]# mkdir -pv /testdir/{dir3,dir4,dir5/{dir6,dir7}}
mkdir: created directory '/testdir/dir3'
mkdir: created directory '/testdir/dir4'
mkdir: created directory '/testdir/dir5'
mkdir: created directory '/testdir/dir5/dir6'
mkdir: created directory '/testdir/dir5/dir7'

文件元数据和节点表结构

inode 表结构

在Linux系统中,一切皆文件,

每个文件,又分为文件元数据和具体内容两部份,

一个文件元数据和其具体内容数据,在磁盘分区上,是分开存放的。

这种存储文件元数据的区域就叫 inode,中文译作 “索引节点”,

每个文件都有一个 inode 和 n(n>=1) 个 block 数据块,inode 存储文件元数据,数据块存储文件具体内容数据,

磁盘在格式化时,系统会自动将磁盘分为两个区域,

一个是 inode 区(inode table),用来存放文件的 inode,

另一个是数据区,分成很多个block(块),用来存放文件的具体内容数据,

一个磁盘分区上有多少个inode和多少个block,由系统自行决定,跟文件系统,磁盘分区大小,数据块大小有关,

一个磁盘分区,能存放多少个文件,由文件大小,磁盘分区大小,inode数量决定,

inode 编号可重复使用,当删除一个文件之后,其inode 编号会被回收,供下次新文件使用,

4

每一个inode表记录对应的保存了以下信息:

  • inode number(索引节点编号)
  • 文件类型
  • 权限
  • 属主属组
  • 链接数
  • 文件大小
  • 各时间戳
  • 指向具体数据块的指针
  • 有关文件的其他数据

5

以指针大小为4字节,block块大小为4KB为前置条件

指针大小和block 块大小跟操作系统平台,以及文件系统有关;

直接指针

12个直接指针,直接指向具体数据块,如果block 大小为 4096(4K),则直接指针可以保存 48KB的文件

间接指针

1个间接指针,指向一个数据块,只不过该block上保存的是指针,而不是具体数据

如果block 大小为 4096(4K),一个指针占用4字节,所以此处可以存储 4096/4=1024个 block 地址;

则可以存储的数据大小为 1024*4096=4MB

双重间接指针

1个双重间接指针,指向一个数据块,只不过该block上保存的是指针,而不是具体数据

如果block 大小为 4096(4K),一个指针占用4字节,所以此处可以存储 4096/4=1024个 block 地址;

同理,其指向的 1024个block上,也都是存储的指针地址;

则此处可以存储的数据大小为 1024x1024x4096=4GB

三重间接指针

1个三重间接指针,指向一个数据块,只不过该block上保存的是指针,而不是具体数据

如果block 大小为 4096(4K),一个指针占用4字节,所以此处可以存储 4096/4=1024个 block 地址;

同理,其指向的 1024个block上,也都是存储的指针地址 则此处可以存储的数据大小为 1024x1024x1024x4096=4TB

单文件最大容量

12x直接指针 + 间接指针 + 双重间接指针 + 三重间接指针

目录

目录是个特殊文件,目录文件的内容保存了此目录中文件的列表及inode number对应关系

  • 文件引用一个是 inode号
  • 人是通过文件名来引用一个文件
  • 一个目录是目录下的文件名和文件inode号之间的映射

inode表和目录

6

cp和inode

cp 命令:

  • 分配一个空闲的inode号,在inode表中生成新条目
  • 在目录中创建一个目录项,将名称与inode编号关联
  • 拷贝数据生成新的文件

rm和inode

rm 命令:

  • 链接数递减,从而释放的inode号可以被重用
  • 把数据块放在空闲列表中
  • 删除目录项
  • 数据实际上不会马上被删除,但当另一个文件使用数据块时将被覆盖

mv和inode

  • 如果mv命令的目标和源在相同的文件系统,作为mv 命令 用新的文件名创建对应新的目录项 删除旧目录条目对应的旧的文件名 不影响inode表(除时间戳)或磁盘上的数据位置:没有数据被移动!
  • 如果目标和源在一个不同的文件系统, mv相当于cp和rm

范例:查看文件系统类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@rocky8 ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 877M 0 877M 0% /dev
tmpfs tmpfs 896M 0 896M 0% /dev/shm
tmpfs tmpfs 896M 8.7M 887M 1% /run
tmpfs tmpfs 896M 0 896M 0% /sys/fs/cgroup
/dev/mapper/rl-root xfs 130G 2.9G 128G 3% /
/dev/mapper/rl-home xfs 65G 497M 65G 1% /home
/dev/sda1 xfs 1014M 212M 803M 21% /boot
tmpfs tmpfs 180M 0 180M 0% /run/user/0

[root@rocky8 ~]# cat /etc/fstab
/dev/mapper/rl-root / xfs defaults 0 0
UUID=a8e3c539-a7e7-4828-9a4d-08a9ec290d07 /boot xfs defaults 0 0
/dev/mapper/rl-home /home xfs defaults 0 0
/dev/mapper/rl-swap none swap defaults 0 0

范例:查看分区inode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8 ~]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
devtmpfs 224364 394 223970 1% /dev
tmpfs 229154 1 229153 1% /dev/shm
tmpfs 229154 594 228560 1% /run
tmpfs 229154 17 229137 1% /sys/fs/cgroup
/dev/mapper/rl-root 68157440 52706 68104734 1% /
/dev/mapper/rl-home 34078720 3 34078717 1% /home
/dev/sda1 524288 310 523978 1% /boot
tmpfs 229154 5 229149 1% /run/user/0

#查看指定分区
[root@rocky8 ~]# df -i /boot
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 524288 310 523978 1% /boot
[root@rocky8 ~]# df -i /dev/sda1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 524288 310 523978 1% /boot

范例:查看文件inode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@rocky8 ~]# ll -i abc 
403579895 -rw-r--r--. 1 root root 0 Aug 26 15:35 abc

[root@rocky8 ~]# ls -i abc
403579895 abc

[root@rocky8 ~]# stat abc
File: abc
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd00h/64768d Inode: 403579895 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2024-08-26 15:35:19.342504991 +0800
Modify: 2024-08-26 15:35:19.342504991 +0800
Change: 2024-08-26 15:35:19.342504991 +0800
Birth: 2024-08-26 15:35:19.342504991 +0800

[root@rocky8 ~]# stat -c "%i" abc
403579895

inode编号耗尽 & 磁盘打满

1
2
3
4
5
6
7
8
9
10
11
#分区越大,可用的节点编号就越多,当前分区有多少个节点编号,就是说能在当前分区上创建多少个文件
#如果当前分区上的节点编号用光,则无法再创建新文件,系统会提示 “No space left on device”
#如果当前分区上的空间用光,同样无法创建新文件,系统同样提示 “No space left on device”


echo test-{1..523977}.txt | xargs touch #创建大量空文件耗尽inode号
cp /dev/zero /tmp/ #创真实大文件把硬盘打满


df -i #查看磁盘分区inode编号使用情况
df -lh #查看磁盘分区使用情况

磁盘分区还有空间,但提示没有足够空间创建文件,这就是因为 inode 编号耗尽的原因

7

inode 编号资源还有,但磁盘数据空间被耗尽,同样无法创建文件

8

范例:删除大文件

1
[root@rocky86 ~]# cat /dev/null > /var/log/huge.log

硬(hard)链接

hard link

硬链接的作用是允许一个文件拥有多个有效的路径名,

新增一个文件,指向某个文件的inode,这样,这两个文件就互为硬链接,

也就是多个文件名,都是指向同一个inode,这是硬链接的本质。

9

硬链接特性

  • 创建硬链接会在对应的目录中增加额外的记录项以引用文件
  • 对应于同一文件系统上一个物理文件
  • 每个目录引用相同的inode号
  • 创建时链接数递增
  • 删除文件时:rm命令递减计数的链接,文件要存在,至少有一个链接数,当链接数为零时,该文件被删除
  • 不能跨越驱动器或分区
  • 不支持对目录创建硬链接

格式:

1
ln filename linkname

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# .  表示当前目录,目录名也表示当前目录,所以是有2次引用
# .. 表示上级目录,上级目录名引用一次,上级目录中的 . 引用一次,子目录中的 .. 引用一次,所是是3次引用

[root@rocky8 dir1]# ll -ai
total 0
'被引用次数'
768482 drwxr-xr-x. 2 root root 6 Aug 26 15:56 .
402653313 dr-xr-x---. 3 root root 168 Aug 26 15:56 ..

[root@rocky8 dir1]# touch a
[root@rocky8 dir1]# ll
total 0
-rw-r--r--. 1 root root 0 Aug 26 16:02 a

[root@rocky8 dir1]# ln a b
[root@rocky8 dir1]# ll
total 0
-rw-r--r--. 2 root root 0 Aug 26 16:02 a
-rw-r--r--. 2 root root 0 Aug 26 16:02 b

符号 symbolic (或软 soft)链接

symbolic link,也称为符号链接,类似于windows 中的快捷方式,

软链接是建立一个独立的文件,这个文件的指向的是目标的文件名。

10

软链接特点

  • 一个符号链接的内容是它引用文件的名称
  • 可以对目录创建软链接
  • 可以跨分区的文件实现
  • 指向的是另一个文件的路径;其大小为指向的路径字符串的长度;不增加或减少目标文件inode的引用计数
  • 软链接如果使用相对路径,是相对于原文件的路径,而非相对于当前目录
  • 删除软链接本身,不会删除源目录内容
  • 删除源目录的文件,不会删除链接文件

格式:

1
ln -s filename linkname

范例: 查看软链接

1
2
3
4
5
6
7
8
9
10
11
[root@rocky8 ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Oct 9 2021 /bin/sh -> bash

[root@rocky8 ~]# ll /bin
lrwxrwxrwx. 1 root root 7 Oct 11 2021 /bin -> usr/bin

[root@rocky8 ~]# readlink /bin/sh
bash

[root@rocky8 ~]# readlink /bin
usr/bin

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#创建跨目录的软链接时,源文件不能以当前路径为准,要以目标文件的路径为准(绝对路径或者目标文件的相对路径)

#错误
[root@rocky86 /]# ln -sv abc /boot/abc.link
'/boot/abc.link' -> 'abc'

[root@rocky86 /]# ll /boot/abc.link
lrwxrwxrwx 1 root root 3 Jul 12 15:08 /boot/abc.link -> abc

#正确
[root@rocky86 /]# ln -sv /root/abc /boot/abc.link2
'/boot/abc.link2' -> '/root/abc'

[root@rocky86 /]# ll /boot/abc.link2
lrwxrwxrwx 1 root root 9 Jul 12 15:10 /boot/abc.link2 -> /root/abc

#正确
[root@rocky86 /]# ln -sv ../root/abc /boot/abc.link3
'/boot/abc.link3' -> '../root/abc'

[root@rocky86 /]# ll /boot/abc.link3
lrwxrwxrwx 1 root root 11 Jul 12 15:12 /boot/abc.link3 -> ../root/abc

范例:删除软链接

1
2
3
4
5
6
7
8
9
10
[root@rocky86 0712]# ll
total 0
drwxr-xr-x 2 root root 48 Jul 12 15:17 dir1
lrwxrwxrwx 1 root root 5 Jul 12 15:18 dir1.link -> dir1/

#这样是删除链接指向的目录
[root@rocky86 0712]# rm -rf dir1.link/

#这样是删除链接文件
[root@rocky86 0712]# rm -rf dir1.link

硬链接和软链接区别总结

硬链接 软连接
本质 本质是同一个文件 本质不是同一个文件
跨设备 不支持 支持
inode 相同 不同
链接数 创建新的硬链接,链接数会增加,
删除硬链接,链接数减少
创建或删除,链接数不会变化
文件夹 不支持 支持
相对路径 原始文件相对路径是相对于当前工作目录 原始文件相对路径是相对于链接文件的相对路径
删除源文件 是链接数减一,但链接文件的访问不受影响 链接文件将无法访问
文件类型 和源文件相同 链接文件,和源文件无关

IO 重定向和管道

标准输入和输出

Linux系统中有三个最基本的IO设备

  1. 标准输入设备(stdin):对应终端键盘
  2. 标准输出设备(stdout):对应终端的显示器
  3. 标准错误输出设备(stderr):对应终端的显示器

在Linux系统中,一切皆文件,所以,这三个设备也是以文件的形式存在于系统中;

程序从标准输入文件中获取数据,再将运行结果和错误信息输出到标准输出设备和标准错误输出设备;

在虚拟终端中,标准输入输出设备都是当前的终端窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@rocky86 ~]# ll /dev/std*
lrwxrwxrwx 1 root root 15 Jul 12 10:13 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jul 12 10:13 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jul 12 10:13 /dev/stdout -> /proc/self/fd/1

[root@rocky86 ~]# ll /proc/self/fd/
total 0
lrwx------ 1 root root 64 Jul 12 17:47 0 -> /dev/pts/1
lrwx------ 1 root root 64 Jul 12 17:47 1 -> /dev/pts/1
lrwx------ 1 root root 64 Jul 12 17:47 2 -> /dev/pts/1

[root@rocky86 ~]# tty
/dev/pts/1

11

I/O重定向 redirect

重定向:redirect

I/O重定向:将默认的输入,输出或错误对应的设备改变,指向新的目标

标准输出和错误重新定向

STDOUT 和 STDERR 默认是使用当前终端,但也可以重定向到指定终端或指定文件

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
COMMAND OPERATOR FILE|DEVICE

#覆盖操作符,如果文件存在,会被覆盖
> #把STDOUT重定向到文件
1> #同上
2> #把STDERR重定向到文件
&> #把标准输出和错误都重定向
>& #和上面功能一样,建议使用上面方式


#追加操作符,在原有文件的基础上追加内容
>> #追加标准输出重定向至文件
1>> #同上
2>> #追加标准错误重定向至文件

范例:标准输出至其它终端

1
2
3
4
5
6
[root@rocky86 ~]# tty
/dev/pts/0

[root@rocky86 ~]# cat /etc/fstab > /dev/pts/1

[root@rocky86 ~]# ls > /dev/pts/1

范例:标准错误输出至其它终端

1
2
3
4
5
6
[root@rocky86 ~]# tty
/dev/pts/0

[root@rocky86 ~]# lss 2> /dev/pts/1

[root@rocky86 ~]# cat null 2> /dev/pts/1

范例:重定向至文件

1
2
3
4
5
6
7
8
9
10
11
#标准输出重定向至文件,覆盖
[root@rocky86 ~]# cat fstab > out.log

#标准输出重定向至文件,追加
[root@rocky86 ~]# cat fstab >> out.log

#标准错误输出重定向至文件,覆盖
[root@rocky86 ~]# cat null 2> err.log

#标准错误输出重定向至文件,追加
[root@rocky86 ~]# cat null 2>> err.log

标准输出和错误输出各自定向至不同位置

1
COMMAND > sucess.out 2> /path/to/error.out

范例:同时标准输出和标准错误输出

1
2
3
4
5
[root@rocky86 ~]# ls fstab null
ls: cannot access 'null': No such file or directory
fstab

[root@rocky86 ~]# ls fstab null > out.log 2> err.log

合并标准输出和错误输出为同一个数据流进行重定向

1
2
3
4
5
&>      #覆盖重定向
&>> #追加重定向

COMMAND > /path/to/file.out 2>&1
COMMAND >> /path/to/file.out 2>&1

范例:标准输出和标准错误输出重定向至同一个文件

1
2
3
4
5
6
7
8
9
#标准输出重定向至 out.log,标准错误输出重定向至标准输出
[root@rocky86 ~]# ls fstab null > out.log 2>&1

#标准错误输出重定向到 out.log,标准输出重定向至标准错误输出
[root@rocky86 ~]# ls fstab null 2> out.log 1>&2

[root@rocky86 ~]# ls fstab null &> out.log

[root@rocky86 ~]# ls fstab null >& out.log

错误写法

1
2
3
4
5
#标准错误输出重定向至标准输出之前,要先定义好标准输出的文件
[root@rocky86 ~]# ls fstab null 2>&1 > out.log

#标准输出重定向至标准错误输出之前,要先定义好标准错误输出的文件
[root@rocky86 ~]# ls fstab null 1>&2 2>out.log

范例:清除大文件

1
2
3
4
5
#通用
[root@rocky86 ~]# cat /dev/null > /data/file.log

#依赖于shell类型,不通用
[root@rocky86 ~]# > /data/file.log

范例: 实现标准输出和错误的互换

1
2
3
4
5
6
7
8
#子进程中借用中间文件描述符3,将标准输出和标准错误输出作了对换
[root@rocky86 ~]# (ls fstab null 3>&1 1>&2 2>&3)>right.out 2>err.out

[root@rocky86 ~]# cat right.out
ls: cannot access 'null': No such file or directory

[root@rocky86 ~]# cat err.out
fstab

标准输入重定向

tr 命令

用于转换字符、删除字符和压缩重复的字符。它从标准输入读取数据并将结果输出到标准输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
tr [OPTION]... SET1 [SET2]

#常用选项
-c|-C|--complement #用SET2替换SET1中没有包含的字符
-d|--delete #删除SET1中所有的字符,不转换
-s|--squeeze-repeats #压缩SET1中重复的字符,即删除重复的字符(只留一个)
-t|--truncate-set1 #将SET1用SET2替换,SET2中不够的,就不处理

#常用通配符
[:alnum:] #字母和数字
[:alpha:] #字母
[:digit:] #数字
[:lower:] #小写字母
[:upper:] #大写字母
[:space:] #空白字符
[:print:] #可打印字符
[:punct:] #标点符号
[:graph:] #图形字符
[:cntrl:] #控制(非打印)字符
[:xdigit:] #十六进制字符

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@rocky8 ~]# echo 123123 | tr 123 abc
abcabc
[root@rocky8 ~]# echo 123333 | tr 123 abc
abcccc

#小写转大写
[root@rocky8 ~]# echo 123abcd | tr a-z A-Z
123ABCD

[root@rocky8 ~]# echo 123abcd | tr [:lower:] [:upper:]
123ABCD

#非123就替换成x
[root@rocky8 ~]# echo 1235790 | tr -c 123 x
123xxxxx

#删除2-5
[root@rocky8 ~]# echo 1235790 | tr -d '2-5'
1790

#删除大写字母
[root@rocky8 ~]# echo TDlQToDHvFEeKL | tr -d [:upper:]
love

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#将issue文件中的小写字母换成大写,然后输出
[root@rocky86 ~]# tr [:lower:] [:upper:] </etc/issue
\S
KERNEL \R ON AN \M

#将issue文件中的小写字母换成大写,然后重定向输出到文件
[root@rocky86 ~]# tr [:lower:] [:upper:] </etc/issue > tr.tx

#命令重定向
[root@rocky8 ~]# tr -s ' ' <<<`df`
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 897456 0 897456 0% /dev
tmpfs 916616 0 916616 0% /dev/shm
tmpfs 916616 8872 907744 1% /run
tmpfs 916616 0 916616 0% /sys/fs/cgroup
/dev/mapper/rl-root 136248320 2968480 133279840 3% /
/dev/mapper/rl-home 68124160 508020 67616140 1% /home
/dev/sda1 1038336 216736 821600 21% /boot
tmpfs 183320 0 183320 0% /run/user/0

#同上
[root@rocky86 ~]# tr -s ' ' < <(df)

标准输入重定向

标准输入重定向是使用文件来代替键盘的输入,

从文件中读取数据,代替当前终端的输入设备输入的数据,

此处要严格区分命令是否支持标准输入,标准输入和参数是两个概念;

怎么判断命令能使用标准输入重定向?

不跟任何选项参数,直接回车,看是否等待标准输入,如果是,则该命令可以使用标准输入重定向。

格式:

1
2
3
COMMAND 0< FILE

COMMAND < FILE
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
[root@rocky86 ~]# cat a.txt 
1+2+3+4+5+6+7+8+9+10

#标准输入重定向
[root@rocky86 ~]# bc < a.txt
55

#标准输入输出重定向
[root@rocky86 ~]# bc < a.txt > rs.txt
[root@rocky86 ~]# cat rs.txt
55

#多行执行
[root@rocky86 ~]# seq -s + 1 10 > a.txt;bc<a.txt>rs.txt
[root@rocky86 ~]# cat rs.txt
55

#等价于 cat a.txt
[root@rocky86 ~]# cat < a.txt
1+2+3+4+5+6+7+8+9+10

#先输入重定向,再输出重定向
[root@rocky86 ~]# cat < a.txt > b.txt
[root@rocky86 ~]# cat b.txt
1+2+3+4+5+6+7+8+9+10

#输入重定向,再将输入内容输出重定向
[root@rocky86 ~]# cat > abc.txt

标准输入多行重定向

使用 “<<终止词” 命令从键盘把多行重导向给STDIN,直到终止词位置之前的所有文本都发送给STDIN,

有时被称为就地文本(here documents),其中终止词可以是任何一个或多个符号,

比如:!,@,$,EOF(End Of File),magedu等,其中EOF比较常用

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@rocky86 ~]# cat <<EOF
> 123
> 456
> EOF
123
456

[root@rocky86 ~]# bc <<EOF
> 2+3
> 3^4
> EOF
5
81

范例:多行覆盖

1
2
3
4
5
6
7
8
9
10
[root@rocky86 ~]# cat > abc.txt <<EOF
> 123
> 456
> 789
> EOF

[root@rocky86 ~]# cat abc.txt
123
456
789

范例:

1
2
3
4
5
6
7
8
[root@rocky86 ~]# mail -s "test title" 123456@qq.com <<EOF
> hi
>
> this is test mail
>
> bye
> form mage
> EOF

高级重定向写法

cmd <<< “string”

含义是 here-string ,表示传给给cmd的stdin的内容从这里开始是一个字符串。

范例:直接字符串

1
2
3
4
5
6
7
8
[root@rocky86 ~]# cat <<< "abc"
abc

[root@rocky86 ~]# bc <<< "1+2+3"
6

[root@rocky86 ~]# tr 'a-z' 'A-Z' <<< "welcome to magedu"
WELCOME TO MAGEDU

范例:执行命令作重定向输入

1
2
3
4
5
6
7
8
[root@rocky86 ~]# bc <<< `echo 1+2+3`
6

[root@rocky86 ~]# bc <<< `seq -s + 3`
6

[root@rocky86 ~]# tr 'a-z' 'A-Z' <<< `hostname`
ROCKY86
cmd1 < <(cmd2)

名称为 Process substitution ,是由两个部分组成

<(cmd2) 表示把cmd2的输出写入一个临时文件,注意:< 符号 与( 符号之间没有空格

cmd1 < 这是一个标准的stdin重定向

把两个合起来,就是把cmd2的输出stdout传递给cmd1作为输入stdin, 中间通过临时文件做传递

范例:

1
2
3
4
5
6
7
8
[root@rocky86 ~]# bc < <(echo 1+2+3)
6

[root@rocky86 ~]# bc < <(seq -s + 3)
6

[root@rocky86 ~]# tr 'a-z' 'A-Z' < <(hostname)
ROCKY86

范例:查看中间文件

1
2
[root@rocky8 ~]# ll <(hostname)
lr-x------. 1 root root 64 Aug 26 20:56 /dev/fd/63 -> 'pipe:[33862]'

管道

管道

管道(pipe):名顾思义,水管,从一端进去,再从另一端出来。

在shell 中,可以将两个或多个命令(程序|进程)连接起来,将前一个命令的输出作为后一个命令的输入,就像拿水管将两个命令连起来;

使用管道,要求前一个命令必须支持标准输出,后一个命令必须支持标准输入;

12

格式

1
COMMAND1|COMMAND2|COMMAND3|...

功能说明:

  • 将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
  • 所有命令会在当前shell进程的子shell进程中执行
  • 组合多种工具的功能

注意:STDERR默认不能通过管道转发,可利用2>&1 或 |& 实现,格式如下

1
2
3
COMMAND1 2>&1 | COMMAND2 

COMMAND1 |& COMMAND2

范例:

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 ~]# echo 1+2+3|bc
6

[root@rocky86 ~]# cat /var/log/messages | more

[root@rocky8 ~]# ls --help | grep size

[root@rocky86 ~]# echo $PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin

#多重管道
[root@rocky86 ~]# echo $PATH | tr ':' '\n' | sort
/root/bin
/usr/bin
/usr/local/bin
/usr/local/sbin
/usr/sbin

#多重管道(ifconfig命令需要安装net-tools)
[root@rocky86 ~]# ifconfig | head -n 2 | tail -n 1 | tr -s ' ' | cut -d " " -f 3
192.168.1.11

范例:标准输出和标准错误输出同时使用管道

1
2
3
4
5
6
7
[root@rocky86 ~]# ls fstab null 2>&1 | tr 'a-z' 'A-Z'
LS: CANNOT ACCESS 'NULL': NO SUCH FILE OR DIRECTORY
FSTAB

[root@rocky86 ~]# ls fstab null |& tr 'a-z' 'A-Z'
LS: CANNOT ACCESS 'NULL': NO SUCH FILE OR DIRECTORY
FSTAB

范例:实现邮件服务

1
2
3
4
5
6
7
8
9
[root@rocky86 ~]# vim /etc/mail.rc
set from=3311987957@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=3311987957@qq.com
set smtp-auth-password=meenopnxjawzbfcc
set smtp-auth=login
set ssl-verify=ignore

echo "test email" | mail -s "test" 123456@qq.com

范例:用户密码修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@rocky86 ~]# passwd --stdin jose
Changing password for user jose.
magedu
passwd: all authentication tokens updated successfully.


[root@centos8 ~]#cat pass.txt
centos

[root@rocky86 ~]# passwd --stdin jose < pass.txt
Changing password for user jose.
passwd: all authentication tokens updated successfully.

[root@rocky86 ~]# cat pass.txt | passwd --stdin jose
Changing password for user jose.
passwd: all authentication tokens updated successfully.

[root@rocky86 ~]# echo magedu | passwd --stdin jose
Changing password for user jose.
passwd: all authentication tokens updated successfully.

[root@rocky86 ~]# echo magedu | passwd --stdin jose &> /dev/null

tee 命令

将标准输入复制到每个指定文件,并显示到标准输出

格式

1
2
3
4
5
6
7
8
9
10
tee [OPTION]... [FILE]...


#常用选项
-a|--append #内容追加到给定的文件而非覆盖
-i|--ignore-interrupts #忽略中断信号
-p #对写入非管道的行为排查错误,其使用的是 warn-nopipe
--output-error[=模式] #设置写入出错时的行为 (warn|warn-nopipe|exit|exit-nopipe)

cmd1 | tee [-a ] filename | cmd2

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#接受标准输入,在标准输出上打印,并写文件
[root@rocky86 ~]# tee tee.log

#管道重定向
[root@rocky86 ~]# echo hello | tee tee.log
hello

#tee.log 里面是hello,终端输出是HELLO
[root@rocky86 ~]# echo hello | tee tee.log | tr 'a-z' 'A-Z'
HELLO

#tee.log 和终端输出都是大写
[root@rocky86 ~]# echo hello | tr 'a-z' 'A-Z' | tee tee.log
HELLO

#追加
[root@rocky86 ~]# echo hello | tr 'a-z' 'A-Z' | tee -a tee.log
HELLO

范例:

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky86 ~]# echo {1..100} | tr ' ' + | bc
5050

[root@rocky86 ~]# echo {1..100..2} | tr ' ' + | bc
2500

# seq 输出1-100的每一个数字,-s指定用+隔开数字
[root@rocky86 ~]# seq -s + 1 100 | bc
5050

[root@rocky86 ~]# seq -s+ 1 2 100 | bc
2500

范例:

1
2
3
4
5
6
[root@rocky86 ~]# cat <<EOF | tee tee.log
> 123
> 456
> EOF
123
456