*Linux-文件管理和IO重定向(笔记)

目录

一、文件系统目录结构

(1)文件系统的目录结构

(2)常见的文件系统目录功能

(3)应用程序的组成部分

(4)新版本目录结构变化

(5)Linux下的文件类型

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

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

管道文件

套接字文件

二、文件操作命令

(1)显示当前工作目录

(2)绝对和相对路径 - (描述文件位置的两种方式)

(3)更改目录

(4)列出目录内容 

(5)查看文件状态stat

(6)确定文件内容 

(7)文件通配符

(8)创建空文件和刷新时间

(9)复制文件和目录

(10)移动和重命名文件

(11)删除文件 

(12)目录相关操作

① 显示目录树tree

② 创建目录mkdir

③ 删除空目录rmdir

三、文件元数据和节点表结构

(1)inode表结构

① 查看文件系统类型

② 查看分区inode

③ 查看文件inode

测试:inode编号耗尽 & 磁盘打满

(2)硬链接

(3)软链接 (符号链接)

(4)硬链接和软链接区别总结

面试题

四、IO重定向和管道

(1)标准输入和输出

(2)I/O重定向redirec

1. 标准输出和错误重新定向 

2. 标准输入重定向

① 标准输入多行重定向

② 高级重定向写法

③ tr命令

(3)管道

① tee命令


一、文件系统目录结构

        FHS(Filesystem Hierarchy Standard:文件系统层次化标准)由Linux基金会维护,旨在帮助发行版厂商和开发者遵循共同标准来组织Linux系统或开发软件,它采用树形结构定义了系统中各区域的用途、所需最小文件和目录构成,并提供了例外与矛盾处理方式,是多数Linux版本采用的文件组织形式,其官方网站:https://www.pathname.com/fhs/ 

(1)文件系统的目录结构

        ⚪ 文件和目录被组织成一个单根倒置树结构。

        ⚪ 文件系统从根目录下开始,用“/”表。

        ⚪ 根文件系统(rootfs):root filesystem 。

        ⚪ 标准Linux文件系统(如:ext4),文件名称大小写敏感,例如:MAIL, Mail, mail, mAiL。 

        ⚪ 以 . 开头的文件为隐藏文件。

        ⚪ 路径分隔的 / 。

        ⚪ 文件名最长255个字节。

        ⚪ 包括路径在内文件名称最长4095个字节。

        ⚪ 蓝色-->目录 绿色-->可执行文件 红色-->压缩文件 浅蓝色-->链接文件 灰色-->其他文件。

        ⚪ 除了斜杠和NUL,所有字符都有效,但使用特殊字符的目录名和文件不推荐使用,有些字符需要用引号来引用。

        ⚪ 每个文件都有两类相关数据:元数据:metadata,即属性, 数据:data,即文件内容。

(2)常见的文件系统目录功能

/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相关的安全策略等信息的存储位置

(3)应用程序的组成部分

(4)新版本目录结构变化

        /bin 和 /usr/bin         /sbin 和 /usr/sbin 

        /lib 和/usr/lib            /lib64 和 /usr/lib64

[root@Rocky130 bin]$ll /bin
lrwxrwxrwx. 1 root root 7 Nov  3  2024 /bin -> usr/bin
[root@Rocky130 bin]$ll /sbin
lrwxrwxrwx. 1 root root 8 Nov  3  2024 /sbin -> usr/sbin

[root@Rocky130 bin]$ll /lib
lrwxrwxrwx. 1 root root 7 Nov  3  2024 /lib -> usr/lib
[root@Rocky130 bin]$ll /lib64
lrwxrwxrwx. 1 root root 9 Nov  3  2024 /lib64 -> usr/lib64

(5)Linux下的文件类型

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

#范例:
[root@ubuntu ~]#  ls -l /run/
total 20
-rw-------  1 root  root    0 Jun  3 14:27 agetty.reload
drwxr-xr-x  2 root  root   60 Jun  3 14:27 blkid
drwxr-xr-x  2 root  root  120 Jun  3 14:27 cloud-init
drwxr-xr-x  2 root  root   80 Jun  3 14:27 console-setup
drwxr-xr-x  6 root  root  120 Jun  3 14:43 credentials
-rw-r--r--  1 root  root    4 Jun  3 14:27 crond.pid
----------  1 root  root    0 Jun  3 14:27 crond.reboot
drwx------  2 root  root   40 Jun  3 14:27 cryptsetup
drwxr-xr-x  2 root  root   60 Jun  3 14:27 dbus
prw-------  1 root  root    0 Jun  3 14:27 dmeventd-client
prw-------  1 root  root    0 Jun  3 14:27 dmeventd-server
drwxr-xr-x  2 root  root   60 Jun  3 14:27 fsck
prw-------  1 root  root    0 Jun  3 14:27 initctl
drwx------  2 root  root  100 Jun  3 14:27 initramfs
drwxrwxrwt  4 root  root   80 Jun  3 14:27 lock
drwxr-xr-x  3 root  root   60 Jun  3 14:27 log
drwx------  5 root  root  160 Jun  3 14:27 lvm
srw-rw----  1 root  lxd     0 Jun  3 14:27 lxd-installer.socket
drwxr-xr-x  2 root  root   60 Jun  3 15:19 motd.d

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

        Linux系统中,每种颜色,都有对应的含义,可以根据文件在终端中显示的颜色,来判断是什么类型的文件。颜色与文件类型对应关系,由配置文件定义,可更改(此处的文件类型,可以理解为文件格式)。

vim /etc/DIR_COLORS

管道文件

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

套接字文件

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

二、文件操作命令

(1)显示当前工作目录

        每个shell和系统进程都有一个当前的工作目录 CWD:current work directory 。显示当前shell CWD的绝对路径。

#pwd命令
pwd [-LP]

#常用选项
-P    #显示真实物理路径
-L    #显示链接路径(默认)
[root@Rocky130 ~]$cd /
[root@Rocky130 /]$ls
afs  boot  etc   lib    media  opt   root  sbin  sys  usr
bin  dev   home  lib64  mnt    proc  run   srv   tmp  var
[root@Rocky130 /]$ll -d /bin
lrwxrwxrwx. 1 root root 7 Nov  3  2024 /bin -> usr/bin
[root@Rocky130 /]$cd /bin
[root@Rocky130 bin]$pwd
/bin
[root@Rocky130 bin]$pwd -P
/usr/bin
[root@Rocky130 bin]$pwd -L
/bin

###
[root@Rocky130 ~]$cd /etc
[root@Rocky130 etc]$pwd 
/etc
[root@Rocky130 etc]$pwd -P
/etc
[root@Rocky130 etc]$pwd -L
/etc

(2)绝对和相对路径 - (描述文件位置的两种方式)

        绝对路径

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

        相对路径

                1. 不以斜线开始,而是以当前所在的位置开始
                2. 一般情况下,是指相对于当前工作目录的路径,特殊场景下,是相对于某目录的位置
                3. 可以作为一个简短的形式指定一个文件名

#走绝对路径,从根目录出发
[root@Rocky130 ~]$cd /etc/opt   
  
[root@Rocky130 opt]$pwd
/etc/opt

#走相对路径,从当前目录出发
[root@Rocky130 opt]$ls
chrome

[root@Rocky130 opt]$cd chrome

[root@Rocky130 chrome]$pwd
/etc/opt/chrome

#走相对路径,从当前目录出发
[root@Rocky130 chrome]$cd ../../rpm    (..:返回上一级目录)

[root@Rocky130 rpm]$pwd
/etc/rpm

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

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

[root@Rocky130 ~]$basename /etc/opt/chrome
chrome
[root@Rocky130 ~]$basename /etc/opt
opt

[root@Rocky130 ~]$dirname /etc/opt/chrome
/etc/opt
[root@Rocky130 ~]$dirname /etc/opt
/etc

[root@Rocky130 ~]$basename /
/
[root@Rocky130 ~]$dirname /
/

(3)更改目录

cd [-L|[-P [-e]] [-@]] [dir]

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

cd ..        #切换至父目录
cd -         #切换到上一个目录
cd | cd ~    #切换至当前用户家目录
cd ~username #切换至指定用户家目录
[root@Rocky130 ~]$pwd
/root
[root@Rocky130 ~]$cd /etc
[root@Rocky130 etc]$pwd
/etc
[root@Rocky130 etc]$cd /var/log
[root@Rocky130 log]$pwd
/var/log
[root@Rocky130 log]$cd ../..
[root@Rocky130 /]$cd /etc
[root@Rocky130 etc]$cd -
/
[root@Rocky130 /]$cd -
/etc

###
[root@Rocky130 etc]$cd ..
[root@Rocky130 /]$cd /bin
[root@Rocky130 bin]$pwd
/bin
[root@Rocky130 bin]$pwd -P
/usr/bin

[root@Rocky130 ~]$cd -P /bin
[root@Rocky130 bin]$pwd
/usr/bin

### 
#~ 家目录or主目录 / 根目录 
#root超级管理员可以去其他用户的家目录 普通用户没有权限进入root家目录
[root@Rocky130 ~]$cd ~
[root@Rocky130 ~]$cd /etc
[root@Rocky130 etc]$cd ~
[root@Rocky130 ~]$cd /etc
[root@Rocky130 etc]$cd /root
[root@Rocky130 ~]$cd /home/huhao
[root@Rocky130 huhao]$pwd
/home/huhao
[root@Rocky130 huhao]$cd ~
[root@Rocky130 ~]$cd ~huhao
[root@Rocky130 huhao]$pwd
/home/huhao
相关环境变量
$PWD           #当前目录 
$OLDPWD        #OLDPWD

#cd - --->切换到上一个目录?
#当执行此命令 就会去找$OLDPWD变量 

[root@Rocky130 /]$mkdir A B
[root@Rocky130 /]$ls
A    B    boot  etc   lib    media  opt   root  sbin  sys  usr
afs  bin  dev   home  lib64  mnt    proc  run   srv   tmp  var
[root@Rocky130 /]$cd /A
[root@Rocky130 A]$cd ../B
[root@Rocky130 B]$cd -
/A
[root@Rocky130 A]$cd -
/B
[root@Rocky130 B]$echo $OLDPWD
/A
[root@Rocky130 B]$cd -
/A
[root@Rocky130 A]$echo $OLDPWD
/B
[root@Rocky130 A]$

(4)列出目录内容 

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 系统中,该别名的参数不一样。

#LS_COLORS环境变量中定义的文件类型和对应颜色代码的映射,用于控制ls命令输出时不同文件类型的显示颜色
#格式:<文件类型>=<样式代码>;<颜色代码>,多个文件类型配置用冒号 : 分隔
#

[huhao@Rocky130 ~]$echo $LS_COLORS
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:

#vim /etc/DIR_COLORS
#ubuntu中无此文件
[root@ubuntu /]# ls /etc/DIR_COLORS
ls: cannot access '/etc/DIR_COLORS': No such file or directory

#因此Ubuntu中颜色实在dircolors命令中定义的
[root@ubuntu /]# dircolors -p

#无法直接修改
[root@ubuntu /]# file /usr/bin/dircolors
/usr/bin/dircolors: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=009f17e16852176e9a83abb2317214d90c802125, for GNU/Linux 3.2.0, stripped

#在ubuntu中定义颜色,类似于别名定义,加载.bashrc中即可

(5)查看文件状态stat

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

#查看文件元数据
stat [OPTION]... FILE...

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

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

 属性                

说明

atime
access time
访问时间,即读取文件内容时间,此字段值会延时更新,以降低IO负载            
mtime
modify time
修改内容的时间
ctime
change time
元数据发生变化的时间
#查看文件元数据
[root@Rocky130 ~]$stat motd_dota2
  File: motd_dota2
  Size: 1866      	Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 203271825   Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2025-06-01 19:32:50.316596842 +0800
Modify: 2025-06-01 19:28:20.000000000 +0800
Change: 2025-06-01 19:32:35.417717935 +0800
 Birth: 2025-06-01 19:32:35.408718008 +0800

#目录也是一个文件
[root@Rocky130 ~]$stat /etc
  File: /etc
  Size: 8192      	Blocks: 24         IO Block: 4096   directory
Device: fd00h/64768d	Inode: 201326721   Links: 131
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:etc_t:s0
Access: 2025-06-03 17:50:34.800753140 +0800
Modify: 2025-06-03 15:30:42.674976935 +0800
Change: 2025-06-03 15:30:42.674976935 +0800
Birth: 2025-05-26 18:04:08.555142761 +0800

#查看文件所在分区的信息
[root@Rocky130 ~]$stat -f /etc
  File: "/etc"
    ID: fd0000000000 Namelen: 255     Type: xfs
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 18333696   Free: 16844664   Available: 16844664
Inodes: Total: 36700160   Free: 36567884

#权限-inode-文件名
[root@Rocky130 ~]$stat -c "%a-%i-n" /etc
755-201326721-n

(6)确定文件内容 

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

#常用选项
-b|--brief #只显示结果,不显示文件名
-f|--files-from FILE #从指定文件中获取要处理的文件名
-F|--separator STRING #指定分割符
-L|--dereference #跟随软链接
[root@Rocky130 ~]$cat test.sh
#!/bin/bash

echo "hello world"

[root@Rocky130 ~]$file test.sh
test.sh: Bourne-Again shell script, ASCII text executable

[root@Rocky130 ~]$file -b test.sh
Bourne-Again shell script, ASCII text executable

[root@Rocky130 ~]$file /bin
/bin: symbolic link to usr/bin
[root@Rocky130 ~]$file -L /bin
/bin: directory         #-------> usr/bin
#windos的文本格式和Linux的文本格式的区别

#在Windows下创建win.txt文件 文件内容abc(竖直)
#在Linux下创建linux.txt 内容同上

[root@Rocky130 ~]$rz
[root@Rocky130 ~]$ls
anaconda-ks.cfg  Documents   motd-keyboard  Public     test.sh   win.txt
cman.sh          Downloads   Music          Templates  test.txt
Desktop          motd_dota2  Pictures       test.link  Videos
[root@Rocky130 ~]$nano linux.txt
[root@Rocky130 ~]$cat win.txt
a
b
c
[root@Rocky130 ~]$cat linux.txt
a
b
c
[root@Rocky130 ~]$ll
total 24
-rw-r--r--  1 root root    6 Jun  5 15:29 linux.txt
-rw-r--r--  1 root root    9 Jun  5 15:27 win.txt
...
[root@Rocky130 ~]$file win.txt
win.txt: ASCII text, with CRLF line terminators
[root@Rocky130 ~]$file linux.txt
linux.txt: ASCII text

#hexdump -C 命令的输出展示了文本文件的十六进制和 ASCII 表示形式
[root@Rocky130 ~]$hexdump -C win.txt
00000000  61 0d 0a 62 0d 0a 63 0d  0a                       |a..b..c..|
00000009
[root@Rocky130 ~]$hexdump -C linux.txt
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006
#内容一样但是格式不一样 换行符:Linux-0a(LF) Windows-0d 0a(CR+LF)

[root@Rocky130 ~]$cat -A win.txt
a^M$
b^M$
c^M$
[root@Rocky130 ~]$cat -A linux.txt
a$
b$
c$

#安装转换工具dos2unix
#将文本文件将Windows/dos格式转换为unix/linux格式
apt install dos2unix

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

[root@Rocky130 ~]$file win.txt
win.txt: ASCII text

[root@Rocky130 ~]$ll
total 24
-rw-r--r--  1 root root    6 Jun  5 15:29 linux.txt
-rw-r--r--  1 root root    6 Jun  5 15:47 win.txt

[root@Rocky130 ~]$cat -A win.txt
a$
b$
c$

#将Linux的文本格式转换成Windows的文本格式
[root@Rocky130 ~]$unix2dos win.txt
unix2dos: converting file win.txt to DOS format...
[root@Rocky130 ~]$file win.txt
win.txt: ASCII text, with CRLF line terminators
[root@Rocky130 ~]$ll
total 24
-rw-r--r--  1 root root    6 Jun  5 15:29 linux.txt
-rw-r--r--  1 root root    9 Jun  5 15:50 win.txt
[root@Rocky130 ~]$cat -A win.txt
a^M$
b^M$
c^M$
#转换文件字符集编码

iconv -f <from_encoding> -t <to_encoding> <input_file> -o <output_file>

-f <from_encoding>      #指定源文件的字符编码
-t <to_encoding>        #指定目标字符编码
<input_file>            #输入文件名
-o <output_file>        #输出文件名

(7)文件通配符

        文件通配符可以用来匹配符合条件的多个文件,方便批量管理文件。通配符采用特定的符号,表示特定的含义,此特定符号称为元 meta 字符。

#常见的通配符

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

[root@Rocky130 ~]$mkdir huhao123
[root@Rocky130 ~]$cd huhao123
[root@Rocky130 huhao123]$touch {a..c}.log
[root@Rocky130 huhao123]$ls
a.log  b.log  c.log
[root@Rocky130 huhao123]$ls *log
a.log  b.log  c.log

[root@Rocky130 huhao123]$touch file1.txt file2.txt
[root@Rocky130 huhao123]$ls
a.log  b.log  c.log  file1.txt  file2.txt
[root@Rocky130 huhao123]$ls *txt
file1.txt  file2.txt

[root@Rocky130 huhao123]$ls
a.log  b1  b10  b100  b.log  c.log  file1.txt  file2.txt
[root@Rocky130 huhao123]$cd ~
[root@Rocky130 ~]$cd huhao123

[root@Rocky130 huhao123]$ls *
a.log  b1  b10  b100  b.log  c.log  file1.txt  file2.txt

[root@Rocky130 huhao123]$ls b*
b1  b10  b100  b.log

[root@Rocky130 huhao123]$touch {1..5}
[root@Rocky130 huhao123]$ls
1  2  3  4  5  a.log  b1  b10  b100  b.log  c.log  file1.txt  file2.txt
[root@Rocky130 huhao123]$ls ?
1  2  3  4  5

[root@Rocky130 huhao123]$ls ???
b10

[root@Rocky130 huhao123]$ls b?
b1

[root@Rocky130 huhao123]$touch 胡
[root@Rocky130 huhao123]$touch 胡H
[root@Rocky130 huhao123]$ls ?
1  2  3  4  5  胡
[root@Rocky130 huhao123]$ls 胡*
胡  胡H
[root@Rocky130 huhao123]$ls *H
胡H
[root@Rocky130 huhao123]$ls f*t
file1.txt  file2.txt
[root@Rocky130 huhao123]$ls a*c
abc
[root@Rocky130 huhao123]$ls a?c
abc

[root@Rocky130 huhao123]$ls [0-9]*
1  2  3  4  5
[root@Rocky130 huhao123]$touch {1..3}{a..c}.{bak,conf}
[root@Rocky130 huhao123]$ls
1        1c.bak   2b.bak   3a.bak   3c.conf  a.log  c.log
1a.bak   1c.conf  2b.conf  3a.conf  4        b1     file1.txt
1a.conf  2        2c.bak   3b.bak   5        b10    file2.txt
1b.bak   2a.bak   2c.conf  3b.conf  ab       b100   胡
1b.conf  2a.conf  3        3c.bak   abc      b.log  胡H
[root@Rocky130 huhao123]$ls [0-9]*bak
1a.bak  1b.bak  1c.bak  2a.bak  2b.bak  2c.bak  3a.bak  3b.bak  3c.bak

[root@Rocky130 huhao123]$touch 99
[root@Rocky130 huhao123]$ls [0-9][0-9]
99

[root@Rocky130 huhao123]$ls [0-9]?*
1a.bak   1b.conf  2a.bak   2b.conf  3a.bak   3b.conf
1a.conf  1c.bak   2a.conf  2c.bak   3a.conf  3c.bak
1b.bak   1c.conf  2b.bak   2c.conf  3b.bak   3c.conf

[root@Rocky130 huhao123]$ls [abc]*
ab  abc  a.log  b1  b10  b100  b.log  c.log

[root@Rocky130 huhao123]$ls [^abc]*
1        1b.conf  2a.bak   2c.bak   3a.conf  3c.conf    file2.txt
1a.bak   1c.bak   2a.conf  2c.conf  3b.bak   4          胡
1a.conf  1c.conf  2b.bak   3        3b.conf  5          胡H
1b.bak   2        2b.conf  3a.bak   3c.bak   file1.txt

[root@Rocky130 huhao123]$ls [^a-c]*
1        1b.conf  2a.bak   2c.bak   3a.conf  3c.conf    file2.txt
1a.bak   1c.bak   2a.conf  2c.conf  3b.bak   4          胡
1a.conf  1c.conf  2b.bak   3        3b.conf  5          胡H
1b.bak   2        2b.conf  3a.bak   3c.bak   file1.txt

[root@Rocky130 huhao123]$ls [^0-9]*
ab  abc  a.log  b1  b10  b100  b.log  c.log  file1.txt  file2.txt  胡  胡H

[root@Rocky130 huhao123]$touch {X..Y}{x..y}
[root@Rocky130 huhao123]$ls [a-z]*
ab  abc  a.log  b1  b10  b100  b.log  c.log  file1.txt  file2.txt

[root@Rocky130 huhao123]$ls [a-Z]*
ls: cannot access '[a-Z]*': No such file or directory

[root@Rocky130 huhao123]$ls [A-Z]*
Xx  Xy  Yx  Yy

[root@Rocky130 huhao123]$ls [a-zA-Z]*
ab   a.log  b10   b.log  file1.txt  Xx  Yx
abc  b1     b100  c.log  file2.txt  Xy  Yy

[root@Rocky130 huhao123]$ls [a-zA-Z0-9]*
1        1c.bak   2b.bak   3a.bak   3c.conf  a.log  c.log      Yx
1a.bak   1c.conf  2b.conf  3a.conf  4        b1     file1.txt  Yy
1a.conf  2        2c.bak   3b.bak   5        b10    file2.txt
1b.bak   2a.bak   2c.conf  3b.conf  ab       b100   Xx
1b.conf  2a.conf  3        3c.bak   abc      b.log  Xy

[root@Rocky130 huhao123]$ls [abXY012]*
1        1b.bak   1c.conf  2a.conf  2c.bak   abc    b10    Xx  Yy
1a.bak   1b.conf  2        2b.bak   2c.conf  a.log  b100   Xy
1a.conf  1c.bak   2a.bak   2b.conf  ab       b1     b.log  Yx
#另外还有在Linux系统中预定义的字符类表示法如下:man 7 glob
#使用时候得再加[],否则会被当作匹配[]中的字符来用
[:digit:]     #任意数字,相当于0-9
[:lower:]     #任意小写字母,表示 a-z
[:upper:]     #任意大写字母,表示 A-Z 
[:alpha:]     #任意大小写字母
[:alnum:]     #任意数字或字母
[:blank:]     #水平空白字符
[:space:]     #水平或垂直空白字符
[:punct:]     #标点符号
[:print:]     #可打印字符
[:cntrl:]     #控制(非打印)字符
[:graph:]     #图形字符
[:xdigit:]    #十六进制字符

#范例
[root@Rocky130 huhao123]$ls
1        1c.conf  2c.bak   3b.conf  ab     b.log      file2.txt  xC  Yy
1a.bak   2        2c.conf  3c.bak   abc    c.log      xa         xd  胡
1a.conf  2a.bak   3        3c.conf  a.log  f1         xA         xD  胡H
1b.bak   2a.conf  3a.bak   4        b1     f2         xb         Xx
1b.conf  2b.bak   3a.conf  5        b10    f3         xB         Xy
1c.bak   2b.conf  3b.bak   99       b100   file1.txt  xc         Yx

[root@Rocky130 huhao123]$ls [[:digit:]]*
1        1b.bak   1c.conf  2a.conf  2c.bak   3a.bak   3b.conf  4
1a.bak   1b.conf  2        2b.bak   2c.conf  3a.conf  3c.bak   5
1a.conf  1c.bak   2a.bak   2b.conf  3        3b.bak   3c.conf  99

[root@Rocky130 huhao123]$ls [[:lower:]]*
ab   a.log  b10   b.log  f1  f3         file2.txt  xA  xB  xC  xD
abc  b1     b100  c.log  f2  file1.txt  xa         xb  xc  xd

[root@Rocky130 huhao123]$ls [[:upper:]]*
Xx  Xy  Yx  Yy
#补充:[ ] 和 { }
[root@Rocky130 huhao123]$touch x{a..d}
[root@Rocky130 huhao123]$touch x{A..D}
[root@Rocky130 huhao123]$ls x[a-d]
xa  xb  xc  xd
[root@Rocky130 huhao123]$ls x[A-D]
xA  xB  xC  xD

ubuntu
[a-z]:abcdefg...xyz

cenos(旧)
[a-z]:aAbBcCdDeEfFgG...xXyYz

#补充:比较有无*的功能区别
ls *      #等同于 ls 列出当前目录内容,不包括 . 和 ..
ls -a *   #等同于 ls 列出当前目录内容,不包括 . 和 ..
ls -a     #列出当前目录所有内容,包括 . 和 ..
ls .*     #列出当前目录和上级目录的内容, .* 包括 .. 也就是上级目录     
ls -d .*  #只显示当前目录的内容,有预定的别名 l.

(8)创建空文件和刷新时间

#touch命令可以用来创建空文件或刷新文件的时间
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                #如果文件不存在,不创建

(9)复制文件和目录

#利用 cp(copy)命令可以实现文件或目录的复制
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.~#~ ,可以保留
多个版本
源/
不存在
存在且为文件
存在且为目录
一个文件
新建 DEST, 并将 SRC 中内容填充至DEST

将SRC中的内容覆盖至DEST中。注意数据丢失风险,建议用 –i 选项!

在DEST下新建与原文件同名的文件,并将SRC中内容填充至新文件中
多个文件
提示错误
提示错误
在DEST下新建与原文件同名的文件,并将原文件内容复制进新文件中
目录需使用-r选项创建指定DEST同名目录,复制SRC目录中所有文件至DEST下
提示错误
在DEST下新建与原目录同名的目录,并将SRC中内容复制至新目录中

#复制-b先备份再覆盖   - 但只有一个备份

[root@ubuntu huhao123]# touch a.txt
[root@ubuntu huhao123]# ls
a.txt  dira  dirb  f1  f2  issue  issue.bak

[root@ubuntu huhao123]# echo "hu">a.txt
[root@ubuntu huhao123]# cat a.txt
hu
[root@ubuntu huhao123]# ll
total 28
-rw-r--r-- 1 root root    3 Jun  5 20:14 a.txt
[root@ubuntu huhao123]# cp a.txt a2.txt
[root@ubuntu huhao123]# ll
total 32
-rw-r--r-- 1 root root    3 Jun  5 20:14 a2.txt
-rw-r--r-- 1 root root    3 Jun  5 20:14 a.txt

[root@ubuntu huhao123]# echo "12345678" > a.txt
[root@ubuntu huhao123]# ll
total 32
-rw-r--r-- 1 root root    3 Jun  5 20:14 a2.txt
-rw-r--r-- 1 root root    9 Jun  5 20:15 a.txt
[root@ubuntu huhao123]# cp -i a.txt a2.txt
cp: overwrite 'a2.txt'? n
[root@ubuntu huhao123]# cp -b a.txt a2.txt
[root@ubuntu huhao123]# ls
a2.txt  a2.txt~  a.txt  dira  dirb  f1  f2  issue  issue.bak
[root@ubuntu huhao123]# ll
total 36
-rw-r--r-- 1 root root    9 Jun  5 20:15 a2.txt
-rw-r--r-- 1 root root    3 Jun  5 20:14 a2.txt~
-rw-r--r-- 1 root root    9 Jun  5 20:15 a.txt
[root@ubuntu huhao123]# cat a2.txt~
hu
[root@ubuntu huhao123]# cp -b a.txt a2.txt
[root@ubuntu huhao123]# ll
total 36
-rw-r--r-- 1 root root    9 Jun  5 20:17 a2.txt
-rw-r--r-- 1 root root    9 Jun  5 20:15 a2.txt~
-rw-r--r-- 1 root root    9 Jun  5 20:15 a.txt
———————————————————————————————————————————————————————————————————————————————————————————
#--backup=numbered 可以有多条备份

[root@ubuntu huhao123]# rm -rf a*
[root@ubuntu huhao123]# ls
dira  dirb  f1  f2  issue  issue.bak

[root@ubuntu huhao123]# echo "1">a.txt
[root@ubuntu huhao123]# ll
total 28
-rw-r--r-- 1 root root    2 Jun  5 20:25 a.txt
[root@ubuntu huhao123]# cp --backup=numbered a.txt a2.txt
[root@ubuntu huhao123]# ll
total 32
-rw-r--r-- 1 root root    2 Jun  5 20:26 a2.txt
-rw-r--r-- 1 root root    2 Jun  5 20:25 a.txt

[root@ubuntu huhao123]# echo "22">a.txt
[root@ubuntu huhao123]# cp --backup=numbered a.txt a2.txt
[root@ubuntu huhao123]# ll
total 36
-rw-r--r-- 1 root root    3 Jun  5 20:26 a2.txt
-rw-r--r-- 1 root root    2 Jun  5 20:26 a2.txt.~1~
-rw-r--r-- 1 root root    3 Jun  5 20:26 a.txt

[root@ubuntu huhao123]# echo "333">a.txt
[root@ubuntu huhao123]# cp --backup=numbered a.txt a2.txt
[root@ubuntu huhao123]# ll
total 40
-rw-r--r-- 1 root root    4 Jun  5 20:27 a2.txt
-rw-r--r-- 1 root root    2 Jun  5 20:26 a2.txt.~1~
-rw-r--r-- 1 root root    3 Jun  5 20:26 a2.txt.~2~
-rw-r--r-- 1 root root    4 Jun  5 20:27 a.txt
———————————————————————————————————————————————————————————————————————————————————————————
#范例:
#cp -a 保留属性信息
[root@ubuntu huhao123]# stat /var/log/btmp
  File: /var/log/btmp
  Size: 2304      	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 2625139     Links: 1
Access: (0660/-rw-rw----)  Uid: (    0/    root)   Gid: (   43/    utmp)
Access: 2025-06-01 14:53:15.891345159 +0800
Modify: 2025-06-01 17:33:21.530539293 +0800
Change: 2025-06-01 17:33:21.530539293 +0800
 Birth: 2025-06-01 14:53:15.891345159 +0800
[root@ubuntu huhao123]# cp /var/log/btmp ./a
[root@ubuntu huhao123]# stat a
  File: a
  Size: 2304      	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 262267      Links: 1
Access: (0640/-rw-r-----)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-06-05 20:43:32.306175365 +0800
Modify: 2025-06-05 20:43:32.315175448 +0800
Change: 2025-06-05 20:43:32.315175448 +0800
 Birth: 2025-06-05 20:43:32.306175365 +0800
[root@ubuntu huhao123]# cp -a /var/log/btmp ./a2
[root@ubuntu huhao123]# stat a2
  File: a2
  Size: 2304      	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 262268      Links: 1
Access: (0660/-rw-rw----)  Uid: (    0/    root)   Gid: (   43/    utmp)
Access: 2025-06-05 20:43:32.315175448 +0800
Modify: 2025-06-01 17:33:21.530539293 +0800
Change: 2025-06-05 20:44:00.550759226 +0800
 Birth: 2025-06-05 20:44:00.549438291 +0800

#cp -v 显示复制过程
[root@ubuntu huhao123]# touch f1
[root@ubuntu huhao123]# cp f1 f2
[root@ubuntu huhao123]# cp -v f1 f3
'f1' -> 'f3'
[root@ubuntu huhao123]# ls
f1  f2  f3

(10)移动和重命名文件

        mv 命令可以实现文件或目录的移动和改名。同一分区移动数据,速度很快,数据位置没有变化。不同分区移动数据,速度相对慢,数据位置发生了变化。

mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE...

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

#提动前备份
[root@ubuntu huhao123]# mv -b f0 f2
[root@ubuntu huhao123]# ls
f2  f2~

#移动多个文件到目录
[root@ubuntu huhao123]# mkdir dira
[root@ubuntu huhao123]# tree
.
├── dira
├── f2
└── f2~

2 directories, 2 files
[root@ubuntu huhao123]# mv f2 f2~ ./dira
[root@ubuntu huhao123]# ls
dira
[root@ubuntu huhao123]# tree
.
└── dira
    ├── f2
    └── f2~

2 directories, 2 files

[root@ubuntu huhao123]# mv dira dirb
[root@ubuntu huhao123]# ls
dirb
[root@ubuntu huhao123]# mkdir dirx
[root@ubuntu huhao123]# touch dirx/{x..z}.log
[root@ubuntu huhao123]# tree
.
├── dirb
│   ├── f2
│   └── f2~
└── dirx
    ├── x.log
    ├── y.log
    └── z.log

3 directories, 5 files
[root@ubuntu huhao123]# mv dirx dirb 
[root@ubuntu huhao123]# tree
.
└── dirb
    ├── dirx
    │   ├── x.log
    │   ├── y.log
    │   └── z.log
    ├── f2
    └── f2~

3 directories, 5 files
#利用 rename 可以批量修改文件名
rename [options] <expression> <replacement> <file>...

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

#范例
centos
[root@Rocky130 huhao123]$touch f-{1..3}.{conf,log}
[root@Rocky130 huhao123]$ls
f-1.conf  f-1.log  f-2.conf  f-2.log  f-3.conf  f-3.log  issue

#为所有的f开头包含conf的文件加上.bak后缀
[root@Rocky130 huhao123]$rename 'conf' 'conf.bak' f*

[root@Rocky130 huhao123]$ls
f-1.conf.bak  f-2.conf.bak  f-3.conf.bak  issue
f-1.log       f-2.log       f-3.log

#去掉所有的bak后缀
[root@Rocky130 huhao123]$rename '.bak' '' *bak

[root@Rocky130 huhao123]$ls
f-1.conf  f-1.log  f-2.conf  f-2.log  f-3.conf  f-3.log  issue
[root@Rocky130 huhao123]$touch {x..z}.txt
[root@Rocky130 huhao123]$ls
f-1.conf  f-2.conf  f-3.conf  issue  y.txt
f-1.log   f-2.log   f-3.log   x.txt  z.txt

#将当前目录下以.txt结尾的文件,批量改名成 .log结尾
[root@Rocky130 huhao123]$rename -v 'txt' 'log' *.txt
`x.txt' -> `x.log'
`y.txt' -> `y.log'
`z.txt' -> `z.log'

[root@Rocky130 huhao123]$ls
f-1.conf  f-2.conf  f-3.conf  issue  y.log
f-1.log   f-2.log   f-3.log   x.log  z.log

#将link.sh指向的文件由a.sh改成b.sh
[root@Rocky130 ~]$ln -sv a.sh link.sh
'link.sh' -> 'a.sh'
[root@Rocky130 ~]$rename -s a.sh b.sh link.sh
[root@Rocky130 ~]$ll link.sh
lrwxrwxrwx 1 root root 4 Jun  6 14:37 link.sh -> b.sh

ubuntu
[root@ubuntu huhao123]# rename 's/conf$/conf.bak/' f*
[root@ubuntu huhao123]# ls
f-1.conf.bak  f-2.conf.bak  f-3.conf.bak
f-1.log       f-2.log       f-3.log

(11)删除文件 

#使用 rm 命令可以删除文件和目录
#注意:此命令非常危险,慎重使用,我建议使用 mv 代替 rm
rm [OPTION]... [FILE]...

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

#范例
ubuntu
[root@ubuntu huhao123]# tree
.
└── dira
    ├── dirb
    │   ├── a
    │   └── b
    ├── x1
    ├── x2
    ├── y1
    ├── y2
    ├── z1
    └── z2

3 directories, 8 files
[root@ubuntu huhao123]# rm *
rm: cannot remove 'dira': Is a directory

[root@ubuntu huhao123]# rm -i dira/x{1,2}
rm: remove regular empty file 'dira/x1'? y
rm: remove regular empty file 'dira/x2'? y
[root@ubuntu huhao123]# rm dira/y{1,2}
[root@ubuntu huhao123]# tree
.
└── dira
    ├── dirb
    │   ├── a
    │   └── b
    ├── z1
    └── z2

3 directories, 4 files
[root@ubuntu huhao123]# rm -f dira/z{1,2}
[root@ubuntu huhao123]# tree
.
└── dira
    └── dirb
        ├── a
        └── b

3 directories, 2 files
[root@ubuntu huhao123]# rm -r *
[root@ubuntu huhao123]# ls

rocky
[root@Rocky130 huhao123]$alias rm
alias rm='rm -i'
[root@Rocky130 huhao123]$tree
.
└── dira
    ├── dirb
    │   ├── a
    │   └── b
    ├── x1
    ├── x2
    ├── y1
    ├── y2
    ├── z1
    └── z2

2 directories, 8 files
[root@Rocky130 huhao123]$rm dira/*
rm: cannot remove 'dira/dirb': Is a directory
rm: remove regular empty file 'dira/x1'? y
rm: remove regular empty file 'dira/x2'? y
rm: remove regular empty file 'dira/y1'? y
rm: remove regular empty file 'dira/y2'? y
rm: remove regular empty file 'dira/z1'? y
rm: remove regular empty file 'dira/z2'? y

[root@Rocky130 huhao123]$rm -rf *
[root@Rocky130 huhao123]$ls
[root@Rocky130 huhao123]$


#无法直接删根
[root@ubuntu ~]# rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe
'''
最早时期可实现删除根目录
[root@Rocky130 ~]$file=issue
[root@Rocky130 ~]$echo $file
issue
[root@Rocky130 ~]$echo /$file 
/issue
[root@Rocky130 ~]$echo /$flie
/
--> rm -rf /$flie == rm -rf /
'''

#删除当前目录所有内容
[root@ubuntu ~]# rm -rf *

#特殊情况 - 无法删除 
①[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# echo "123" > -f
[root@ubuntu huhao123]# ls
-f
[root@ubuntu huhao123]# rm -rf -f    #-f文件误认为是选项 无法删除 
[root@ubuntu huhao123]# ls
-f
[root@ubuntu huhao123]# rm -rf *
[root@ubuntu huhao123]# ls
-f
#解决->
[root@ubuntu huhao123]# rm -rf ./-f
[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# 

②[root@ubuntu huhao123]# touch ~
[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# touch '~'
[root@ubuntu huhao123]# ls
'~'
[root@ubuntu huhao123]# rm ~
rm: cannot remove '/root': Is a directory
[root@ubuntu huhao123]# rm -r ~^C
[root@ubuntu huhao123]# rm -rf ./~
[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# 

#!避免误删除 定义别名
[root@ubuntu huhao123]# alias rm='mv -t /tmp'

[root@ubuntu huhao123]# touch hu
[root@ubuntu huhao123]# ls
hu
[root@ubuntu huhao123]# rm hu
[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# ls /tmp
hu
snap-private-tmp
...

(12)目录相关操作

① 显示目录树tree

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             #显示色彩

② 创建目录mkdir

mkdir [OPTION]... DIRECTORY...

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

#范例
#指定权限
mkdir -m=777 dira

#递归创建
[root@Rocky130 huhao123]$mkdir dira/dirb/dirc
mkdir: cannot create directory ‘dira/dirb/dirc’: No such file or directory

[root@Rocky130 huhao123]$mkdir -p dira/dirb/dirc
[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb
        └── dirc

3 directories, 0 files

[root@Rocky130 huhao123]$mkdir -v test 
mkdir: created directory 'test'

[root@Rocky130 huhao123]$rm -rf *
[root@Rocky130 huhao123]$ls
[root@Rocky130 huhao123]$mkdir -pv a/b/c    #组合使用
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
[root@Rocky130 huhao123]$tree
.
└── a
    └── b
        └── c

3 directories, 0 files

③ 删除空目录rmdir

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

rmdir [OPTION]... DIRECTORY...

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

#范例
[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb
        └── dirc

3 directories, 0 files
[root@Rocky130 huhao123]$touch dira/file 
[root@Rocky130 huhao123]$tree
.
└── dira
    ├── dirb
    │   └── dirc
    └── file

3 directories, 1 file
[root@Rocky130 huhao123]$rmdir dira
rmdir: failed to remove 'dira': Directory not empty
[root@Rocky130 huhao123]$rm -rf dira/file 
[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb
        └── dirc

3 directories, 0 files
[root@Rocky130 huhao123]$rmdir dira
rmdir: failed to remove 'dira': Directory not empty
[root@Rocky130 huhao123]$rmdir dira/dirb/dirc
[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb

2 directories, 0 files
[root@Rocky130 huhao123]$rmdir -p dira/dirb
[root@Rocky130 huhao123]$ls
———————————————————————————————————————————————————————————————————————————————————————————
[root@Rocky130 huhao123]$mkdir -pv dira/dirb/dirc
mkdir: created directory 'dira'
mkdir: created directory 'dira/dirb'
mkdir: created directory 'dira/dirb/dirc'
[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb
        └── dirc

3 directories, 0 files
[root@Rocky130 huhao123]$rmdir -pv dira/dirb/dirc
rmdir: removing directory, 'dira/dirb/dirc'
rmdir: removing directory, 'dira/dirb'
rmdir: removing directory, 'dira'

[root@Rocky130 huhao123]$tree
.
└── dira
    └── dirb
        ├── dirc
        └── file1

3 directories, 1 file
[root@Rocky130 huhao123]$rmdir -pv dira/dirb/dirc
rmdir: removing directory, 'dira/dirb/dirc'
rmdir: removing directory, 'dira/dirb'
rmdir: failed to remove directory 'dira/dirb': Directory not empty

三、文件元数据和节点表结构

(1)inode表结构

        在Linux系统中,一切皆文件,每个文件,又分为文件元数据和具体内容两部份,一个文件元数据和其具体内容数据,在磁盘分区上,是分开存放的。这种存储文件元数据的区域就叫 inode,中文译作 "索引节点",每个文件都有一个inode和n(n>=1)个block 数据块,inode 存储文件元数据,数据块存储文件具体内容数据。

        磁盘在格式化时,系统会自动将磁盘分为两个区域,一个是 inode 区(inode table),用来存放文件的 inode,另一个是数据区,分成很多个block(块),用来存放文件的具体内容数据,一个磁盘分区上有多少个inode和多少个block,由系统自行决定,跟文件系统,磁盘分区大小,数据块大小有关,一个磁盘分区,能存放多少个文件,由文件大小,磁盘分区大小,inode数量决定,inode 编号可重复使用,当删除一个文件之后,其inode 编号会被回收,供下次新文件使用。

        每一个inode表记录对应的保存了以下信息:
                ⚪ inode number(索引节点编号)
                ⚪ 文件类型
                ⚪ 权限
                ⚪ 属主属组
                ⚪ 链接数
                ⚪ 文件大小
                ⚪ 各时间戳
                ⚪ 指向具体数据块的指针
                ⚪ 有关文件的其他数据


(此部分了解即可)

以指针大小为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表和目录

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

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

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

#查看磁盘空间使用情况
df [选项] [文件或目录]

#常用选项
-h	        #以人类可读格式显示(如 KB、MB、GB)
-T	        #显示文件系统类型(如 ext4、xfs)
-i	        #显示 inode 使用情况(而非磁盘空间)
-l	        #仅显示本地文件系统(忽略网络文件系统)
-a	        #显示所有文件系统(包括伪文件系统,如 proc、sysfs)

① 查看文件系统类型

[root@ubuntu ~]# df -Th
Filesystem                        Type   Size  Used Avail Use% Mounted on
tmpfs                             tmpfs  160M  1.3M  159M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv ext4    73G  5.1G   64G   8% /
tmpfs                             tmpfs  800M     0  800M   0% /dev/shm
tmpfs                             tmpfs  5.0M     0  5.0M   0% /run/lock
tmpfs                             tmpfs  1.0M     0  1.0M   0% /run/credentials/systemd-journald.service
tmpfs                             tmpfs  1.0M     0  1.0M   0% /run/credentials/systemd-resolved.service
tmpfs                             tmpfs  800M   16K  800M   1% /tmp
/dev/sda2                         ext4   2.0G  111M  1.7G   7% /boot
tmpfs                             tmpfs  1.0M     0  1.0M   0% /run/credentials/systemd-networkd.service
tmpfs                             tmpfs  1.0M     0  1.0M   0% /run/credentials/getty@tty1.service
tmpfs                             tmpfs  160M   12K  160M   1% /run/user/1000
tmpfs                             tmpfs  160M   12K  160M   1% /run/user/0


Filesystem    #显示文件系统对应的设备或分区
Size          #分区的总大小
Used          #已使用的磁盘空间
Avail         #剩余的可用磁盘空间
Use%          #磁盘空间的使用率百分比
Mounted on    #分区的挂载点

② 查看分区inode

[root@ubuntu ~]# df -i
Filesystem                         Inodes  IUsed   IFree IUse% Mounted on
tmpfs                              204583    853  203730    1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 4849664 107112 4742552    3% /
tmpfs                              204583      1  204582    1% /dev/shm
tmpfs                              204583      3  204580    1% /run/lock
tmpfs                                1024      1    1023    1% /run/credentials/systemd-journald.service
tmpfs                                1024      1    1023    1% /run/credentials/systemd-resolved.service
tmpfs                             1048576     22 1048554    1% /tmp
/dev/sda2                          131072    319  130753    1% /boot
tmpfs                                1024      1    1023    1% /run/credentials/systemd-networkd.service
tmpfs                                1024      1    1023    1% /run/credentials/getty@tty1.service
tmpfs                               40916     32   40884    1% /run/user/1000
tmpfs                               40916     33   40883    1% /run/user/0

#可以查看指定分区 后面跟路径

③ 查看文件inode

#范例
[root@ubuntu huhao123]# echo '12345'>a.txt
[root@ubuntu huhao123]# stat a.txt
  File: a.txt
  Size: 6         	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 262248      Links: 1
Access: (0664/-rw-rw-r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-06-06 17:24:44.751573383 +0800
Modify: 2025-06-06 17:24:44.751573383 +0800
Change: 2025-06-06 17:24:44.751573383 +0800
 Birth: 2025-06-06 17:24:44.751573383 +0800

测试:inode编号耗尽 & 磁盘打满

[root@ubuntu huhao123]# cd /boot
[root@ubuntu boot]# mkdir test
[root@ubuntu boot]# cd test
[root@ubuntu test]# pwd
/boot/test
[root@ubuntu test]# df -i /boot
Filesystem     Inodes IUsed  IFree IUse% Mounted on
/dev/sda2      131072   320 130752    1% /boot
[root@ubuntu test]# echo test-{1..131000}.txt | xargs touch    #创建大量空文件耗尽inode号

#复制会话
[root@ubuntu huhao]# for i in {1..100};do df -i /boot;sleep 1;done

SUP->如上图所示,/boot分区的inode已经100%完全耗尽,此时我们touch hu123发现并不能继续创建新文件,用df -lh查看磁盘分区使用情况,发现/boot分区的磁盘空间仅使用7%,但为什么不能继续创建呢?——>inode编号耗尽 (面试题),如果inode编号资源还有,但是磁盘数据空间耗尽,同样无法创建文件!

(2)硬链接

        硬链接的作用是允许一个文件拥有多个有效的路径名。
        新增一个文件,指向某个文件的inode,这样,这两个文件就互为硬链接,也就是多个文件名,都是指向同一个inode,这是硬链接的本质。

ln [options] filename linkname

#常用选项
-s	    #创建符号链接(软链接),默认是硬链接
-f	    #强制覆盖已存在的目标链接
-i	    #覆盖前提示确认(与 -f 互斥)
-v	    #显示操作过程(verbose)

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

# . 表示当前目录,目录名也表示当前目录,所以是有2次引用
# .. 表示上级目录,上级目录名引用一次,上级目录中的 . 引用一次,子目录中的 .. 引用一次,所是是3次引用

[root@ubuntu huhao123]# pwd
/root/huhao123
[root@ubuntu huhao123]# ls
[root@ubuntu huhao123]# ll -ai
total 8
262246 drwxr-xr-x 2 root root 4096 Jun  6 21:09 ./
262145 drwx------ 6 root root 4096 Jun  6 15:18 ../

(3)软链接 (符号链接)

        软链接也称为符号链接,类似于windows 中的快捷方式,软链接是建立一个独立的文件,这个文件的指向的是目标的文件名。

ln [options] filename linkname

#常用选项
-s	    #创建符号链接(软链接),默认是硬链接
-f	    #强制覆盖已存在的目标链接
-i	    #覆盖前提示确认(与 -f 互斥)
-v	    #显示操作过程(verbose)

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

ANS->
① rm -rf dira.link,行为:删除符号链接本身。执行后系统仅直接删除该符号链接文件,该特殊文件存储了指向另一个文件or目录的路径则不会被删除。
②rm -rf dira.link/,行为:解析符号链接并尝试删除其指向的目标(如果是目录,则递归删除目录内容)。执行目录后系统解析符号链接并将其指向的目录dira,尝试删除其内容。

(4)硬链接和软链接区别总结

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

面试题

问题1:提示空间满 No space left on device,但 df 可以看到空间很多,为什么?

        答:由于文件系统的 inode 用尽导致的,而不是存储空间用尽。df -h 命令显示的是文件系统的存储空间使用情况,而 df -ih 命令可以查看 inode 的使用情况。当文件系统的 inode 用尽时,即使还有大量的存储空间,也无法创建新的文件或目录,因为每个文件和目录都需要占用一个 inode,从而出现 No space left on device 的错误。

        解决:① 清理文件系统中大量无用文件以释放inode(快速清理策略需了解);② 增加文件系统inode数量,但通常需要重新格式化文件系统,因此会清空文件系统中的所有数据,提前备份重要数据。

问题2:提示空间快满,使用 rm 删除了很大的无用文件后,df 仍然看到空间不足,为什么?

答:① 文件被进程占用,用 rm 删除一个文件时仅删除文件的目录项和 inode 引用,如果该文件仍然被某个进程打开(例如日志文件被进程持续写入),文件占用的磁盘空间不会立即释放。此时,df 命令会继续显示空间不足,因为文件系统的元数据(如inode和块分配信息)尚未更新。

② 文件系统状态更新的延迟,文件系统可能会缓存文件操作(如删除和写入)和元数据(如块位图)未及时更新,导致空间释放存在延迟,df 可能无法立即反映真实的空间变化。

④ 隐藏文件或目录未删除,可能存在未被注意的隐藏文件(以 . 开头的文件)或删除操作未递归处理深层目录,导致空间未完全释放。


四、IO重定向和管道

(1)标准输入和输出

Linux系统中有三个最基本的IO设备:
        1. 标准输入设备(stdin):对应终端键盘
        2. 标准输出设备(stdout):对应终端的显示器
        3. 标准错误输出设备(stderr):对应终端的显示器

在Linux系统中,一切皆文件,所以,这三个设备也是以文件的形式存在于系统中;程序从标准输入文件中获取数据,再将运行结果和错误信息输出到标准输出设备和标准错误输出设备。

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

(2)I/O重定向redirec

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

1. 标准输出和错误重新定向 

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

COMMAND OPERATOR FILE|DEVICE

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

#追加操作符,在原有文件的基础上追加内容
>>        #追加标准输出重定向至文件
1>>       #同上
2>>       #追加标准错误重定向至文件
[root@ubuntu huhao123]# tty
/dev/pts/0
[root@ubuntu huhao123]# echo 123
123

#标准输出至其他终端
[root@ubuntu huhao123]# echo 123 >/dev/pts/1

#标准错误输出至其它终端
[root@ubuntu huhao123]# echooo 445 2>/dev/pts/1

[root@ubuntu huhao123]# cp /etc/issue .
[root@ubuntu huhao123]# ls
issue
[root@ubuntu huhao123]# ls abc
ls: cannot access 'abc': No such file or directory
[root@ubuntu huhao123]# ls issue abc
ls: cannot access 'abc': No such file or directory
issue

[root@ubuntu huhao123]# ls issue abc >/dev/pts/1
ls: cannot access 'abc': No such file or directory

[root@ubuntu huhao123]# ls issue abc 2>/dev/pts/1
issue

[root@ubuntu huhao123]# ls issue abc 1>/dev/pts/1 2>/dev/pts/1

[root@ubuntu huhao123]# ls issue abc &>/dev/pts/1

#重定向至文件
[root@ubuntu huhao123]# ls issue abc &>rs.txt
[root@ubuntu huhao123]# cat rs.txt
ls: cannot access 'abc': No such file or directory
issue
[root@ubuntu huhao123]# rm -rf rs.txt
[root@ubuntu huhao123]# ls issue abc 1>rs.txt 2>rs.txt
[root@ubuntu huhao123]# cat rs.txt
issue
nnot access 'abc': No such file or directory
'''
注意:此处重定向至同一文件 文件存在则会被覆盖
1.issue
2.ls: cannot access 'abc': No such file or directory在1基础上覆盖issue
则覆盖后nnot access 'abc': No such file or directory 
'''

[root@ubuntu huhao123]# cat issue > issue.sh
[root@ubuntu huhao123]# cat issue.sh
Ubuntu 25.04 \n \l
Welcome Welcome to Linux Demon King - hao \t
[root@ubuntu huhao123]# ls 
issue  issue.sh  rs.txt
[root@ubuntu huhao123]# ls > LS
[root@ubuntu huhao123]# LS
LS: command not found
[root@ubuntu huhao123]# cat LS
issue
issue.sh
LS
rs.txt

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

#格式
COMMAND (1)> sucess.loc 2> /path/to/error.loc

#范例:同时标准输出和标准错误输出 
[root@ubuntu huhao123]# ls
123  error.log  success.log
[root@ubuntu huhao123]# ls 123 456 
ls: cannot access '456': No such file or directory
123
[root@ubuntu huhao123]# ls 123 456 1>success.log 2>error.log
[root@ubuntu huhao123]# cat success.log
123
[root@ubuntu huhao123]# cat error.log
ls: cannot access '456': No such file or directory
[root@ubuntu huhao123]# 

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

&>       #覆盖重定向
&>>      #追加重定向

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

#范例
[root@ubuntu huhao123]# ls 123 456 &>rs.txt 
[root@ubuntu huhao123]# cat rs.txt
ls: cannot access '456': No such file or directory
123
[root@ubuntu huhao123]# ls 123 456 1>rs.txt 2>rs.txt ^C
[root@ubuntu huhao123]# ls 123 456 &>>rs.txt
[root@ubuntu huhao123]# cat rs.txt
ls: cannot access '456': No such file or directory
123
ls: cannot access '456': No such file or directory
123

#标准输出和标准错误输出重定向至同一个文件 
[root@ubuntu huhao123]# ls 123 456
ls: cannot access '456': No such file or directory
123
#标准输出重定向至rs.txt,标准错误输出重定向至标准输出
[root@ubuntu huhao123]# ls 123 456 1>rs.txt 2>&1    #写法2
[root@ubuntu huhao123]# cat rs.txt
ls: cannot access '456': No such file or directory
123

#标准错误输出重定向至rs.txt,标准输出重定向至标准错误输出 
[root@ubuntu huhao123]# ls 123 456 2>rs.txt>&2
[root@ubuntu huhao123]# cat rs.txt
ls: cannot access '456': No such file or directory
123

#注意 ERROR!!!
#标准错误输出重定向至标准输出之前,要先定义好标准输出的文件
[root@ubuntu huhao123]# ls 123 456 2>&1>rs.txt
#标准输出重定向至标准错误输出之前,要先定义好标准错误输出的文件
[root@ubuntu huhao123]# ls 123 456 1>&2>rs.txt
#妙用之清空大文件
echo "" > <bigfile>

#范例
[root@ubuntu huhao123]# cp /var/log/syslog .
[root@ubuntu huhao123]# ls
syslog
[root@ubuntu huhao123]# cat syslog
...
[root@ubuntu huhao123]# ll -h
total 1.4M
drwxr-xr-x 2 root root 4.0K Jun  7 19:43 ./
drwx------ 6 root root 4.0K Jun  7 19:25 ../
-rw-r----- 1 root root 1.4M Jun  7 19:43 syslog
[root@ubuntu huhao123]# echo "">syslog
[root@ubuntu huhao123]# ll -h
total 12K
drwxr-xr-x 2 root root 4.0K Jun  7 19:43 ./
drwx------ 6 root root 4.0K Jun  7 19:25 ../
-rw-r----- 1 root root    1 Jun  7 19:44 syslog
#实现标准输出和错误的互换
[root@ubuntu huhao123]# ls 123 456
ls: cannot access '456': No such file or directory
123
[root@ubuntu huhao123]# (ls 123 456 3>&1 1>&2 2>&3)>right.log 2>error.log
[root@ubuntu huhao123]# cat right.log
ls: cannot access '456': No such file or directory
[root@ubuntu huhao123]# cat error.log
123

2. 标准输入重定向

        标准输入重定向是使用文件(不支持设备)来代替键盘的输入,从文件中读取数据,代替当前终端的输入设备输入的数据,此处要严格区分命令是否支持标准输入,标准输入和参数是两个概念。

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

COMMAND 0< FILE
COMMAND < FILE

#范例
[root@ubuntu huhao123]# echo "1+2+3">a.txt
[root@ubuntu huhao123]# cat a.txt
1+2+3
#标准输入重定向
[root@ubuntu huhao123]# bc < a.txt
6
#标准输入输出重定向 
[root@ubuntu huhao123]# bc < a.txt > rs.txt
[root@ubuntu huhao123]# cat rs.txt
6

'''
seq命令:seq [选项] 起始值 步长 结束值 
seq [选项] 结束值  # 默认从1开始,步长为1

#常用选项
-s        #指定分隔符(默认是换行符 \n)
-f        #指定输出格式(如 -f "%02g" 表示两位数字,不足补零)
-w        #等宽输出(自动补零,使数字宽度一致)
#范例
[root@ubuntu huhao123]# seq 5
1
2
3
4
5
[root@ubuntu huhao123]# seq 1 1 5
1
2
3
4
5
[root@ubuntu huhao123]# seq -s + 5
1+2+3+4+5
'''

#多行执行;先输入重定向,再输出重定向
[root@ubuntu huhao123]# seq -s + 5 > a.txt;bc < a.txt > rs.txt 
[root@ubuntu huhao123]# cat a.txt
1+2+3+4+5
[root@ubuntu huhao123]# cat rs.txt
15

#等价于a.txt 
[root@ubuntu huhao123]# cat < a.txt
1+2+3+4+5

#输入重定向,在将输入内容输出重定向 
[root@ubuntu huhao123]# cat > a.txt
123456
123456
^C
[root@ubuntu huhao123]# cat a.txt
123456
123456
① 标准输入多行重定向

        使用 "<<终止词" 命令从键盘把多行重导向给stdin,直到终止词位置之前的所有文本都发送给stdin,有时被称为就地文本,其中终止词可以是任何一个或多个符号,比如:!,@,$,EOF,其中EOF比较常用。

#范例
[root@ubuntu huhao123]# cat 
1
1
2
2
3
3

#如果想要一次性输入再输出该如何操作呢?
[root@ubuntu huhao123]# cat <<EOF
> 1
> 2
> 3
> EOF
1
2
3

[root@ubuntu huhao123]# bc <<EOF
> 1+2+3
> 100+100
> 50*50
> EOF
6
200
2500

#多行覆盖
[root@ubuntu huhao123]# cat > a.txt <<EOF
> 123
> 321
> 888
> EOF
[root@ubuntu huhao123]# cat a.txt
123
321
888
② 高级重定向写法
cmd <<< "string"
#表示传给cmd的stdin的内容从这里开始是一个字符串

#范例-直接字符串
[root@ubuntu huhao123]# cat <<< "123"
123
[root@ubuntu huhao123]# bc <<< "1+2+3+4+5"
15

#-执行命令作重定向输入
[root@ubuntu huhao123]# bc <<< `echo 1+2+3`
6
[root@ubuntu huhao123]# bc <<< `seq -s + 3`
6
cmd1 < <(cmd2)

#<(cmd2)表示把cmd2的输出写入一个临时文件, 注意:<符号与(符号之间没有空格
#cmd1 <这是一个标准的stdin重定向把两个合起来,就是把cmd2的输出stdout传递给cmd1作为输入stdin,中间通过临时文件做传递

#范例
#[root@ubuntu huhao123]# cat < <(id)
uid=0(root) gid=0(root) groups=0(root)
[root@ubuntu huhao123]# ll <(id)
lr-x------ 1 root root 64 Jun  7 20:48 /dev/fd/63 -> 'pipe:[44162]'|
[root@ubuntu huhao123]# bc < <(echo 1+2+3)
6
[root@ubuntu huhao123]# ll <(echo 1+2+3)
lr-x------ 1 root root 64 Jun  7 20:49 /dev/fd/63 -> 'pipe:[44198]'|
[root@ubuntu huhao123]# bc < <(seq -s + 3)
6
[root@ubuntu huhao123]# ll <(seq -s + 3)
lr-x------ 1 root root 64 Jun  7 20:49 /dev/fd/63 -> 'pipe:[44230]'|


#区别
[root@ubuntu huhao123]# cat < a.txt
123
321
888
[root@ubuntu huhao123]# cat < <(cat a.txt)
123
321
888
#后者:其实是一种进程替换<(cat a.txt)+重定向,会创建临时文件,并将()中输出写入该临时文件,然后输入重定向给cat,其实是一种冗余的写法
#前者:标准的输入重定向,直接文件读取
③ tr命令
#用于转换字符、删除字符和压缩重复的字符
#它从标准输入读取数据并将结果输出到标准输出
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:]        #十六进制字符
#范例 
[root@ubuntu huhao123]# tr 123 abc
111
aaa
222
bbb
333
ccc
123123123
abcabcabc
^C

#小写转大写
[root@ubuntu huhao123]# tr a-z A-Z
abcdefghigklmnopqistuwvxyz
ABCDEFGHIGKLMNOPQISTUWVXYZ
132huhao
132HUHAO
^C
[root@ubuntu huhao123]# tr [:lower:] [:upper:]
abcdefghigklmnopqistuvwxyz
ABCDEFGHIGKLMNOPQISTUVWXYZ
^C

#非123就替换s
[root@ubuntu huhao123]# tr -c 123 x
12345678
123xxxxxx
#非1-5就替换x
[root@ubuntu huhao123]# tr -c "2-5" x
1234567890
x2345xxxxxx

#删除2-5
[root@ubuntu huhao123]# tr -d '2-5' 
1234567888
167888
#删除大写字母
[root@ubuntu huhao123]# tr -d [:upper:]
abcABDEEFasf
abcasf

#将issue文件中的小写字母换成大写
[root@ubuntu huhao123]# cat issue
Ubuntu 25.04 \n \l
Welcome Welcome to Linux Demon King - hao \t
[root@ubuntu huhao123]# tr [:lower:] [:upper:] < issue
UBUNTU 25.04 \N \L
WELCOME WELCOME TO LINUX DEMON KING - HAO \T
#高级
[root@ubuntu huhao123]# tr a-z A-Z <<<`cat issue`
UBUNTU 25.04 \N \L
WELCOME WELCOME TO LINUX DEMON KING - HAO \T
#高级
[root@ubuntu huhao123]# tr a-z A-Z < <(cat issue)
UBUNTU 25.04 \N \L
WELCOME WELCOME TO LINUX DEMON KING - HAO \T

(3)管道

        管道(pipe):名顾思义,水管,从一端进去,再从另一端出来。在shell 中,可以将两个或多个命令(程序|进程)连接起来,将前一个命令的输出作为后一个命令的输入,就像拿水管将两个命令连起来;使用管道,要求前一个命令必须支持标准输出,后一个命令必须支持标准输入。

COMMAND1|COMMAND2|COMMAND3|...

左边命令的输出|右边命令接收输入...

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

#范例
[root@ubuntu huhao123]# seq -s + 100
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+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100
[root@ubuntu huhao123]# seq -s + 100 > a.txt 
[root@ubuntu huhao123]# bc < a.txt
5050
[root@ubuntu huhao123]# seq -s + 100 | a.txt 
a.txt: command not found
[root@ubuntu huhao123]# seq -s + 100 | bc 
5050
[root@ubuntu huhao123]# echo "huhao" | tr a-z A-Z
HUHAO

[root@ubuntu ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/root/.local/bin
[root@ubuntu ~]# echo $PATH|tr ':' '/'
/usr/local/sbin//usr/local/bin//usr/sbin//usr/bin//sbin//bin//usr/games//usr/local/games//snap/bin//root/.local/bin

#多重管道
[root@ubuntu huhao123]# cat issue
Ubuntu 25.04 \n \l
Welcome Welcome to Linux Demon King - hao \t
[root@ubuntu huhao123]# cat issue | tr 'a-z' 'A-Z' | tr -d " "
UBUNTU25.04\N\L
WELCOMEWELCOMETOLINUXDEMONKING-HAO\T

#ifconfi取ip
[root@ubuntu ~]# ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.61.129  netmask 255.255.255.0  broadcast 192.168.61.255
        inet6 fe80::20c:29ff:fe78:a1aa  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:78:a1:aa  txqueuelen 1000  (Ethernet)
        RX packets 22074  bytes 4385125 (4.3 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14090  bytes 4050440 (4.0 MB)
        TX errors 0  dropped 2 overruns 0  carrier 0  collisions 0

[root@ubuntu ~]# ifconfig en33 | head -n 2
en33: error fetching interface information: Device not found
[root@ubuntu ~]# ifconfig ens33 | head -n 2
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.61.129  netmask 255.255.255.0  broadcast 192.168.61.255
[root@ubuntu ~]# ifconfig ens33 | head -n 2 | tail -n 1
        inet 192.168.61.129  netmask 255.255.255.0  broadcast 192.168.61.255
[root@ubuntu ~]# ifconfig ens33 | head -n 2 | tail -n 1 | tr -s " "
 inet 192.168.61.129 netmask 255.255.255.0 broadcast 192.168.61.255
[root@ubuntu ~]# ifconfig ens33 | head -n 2 | tail -n 1 | tr -s " " | cut -d" " -f3
192.168.61.129

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

COMMAND1 2>&1 | COMMAND2 
COMMAND1 |& COMMAND2

① tee命令

        将标准输入复制到每个指定文件,并显示到标准输出(既要又要)。

tee [OPTION]... [FILE]...

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

cmd1 | tee [-a ] filename | cmd2

#范例
[root@ubuntu huhao123]# echo 123
123
[root@ubuntu huhao123]# echo 123 >a.txt
[root@ubuntu huhao123]# echo 123 |tee t.txt
123
[root@ubuntu huhao123]# cat t.txt
123

[root@ubuntu huhao123]# echo hello |tee t.txt |tr 'a-z' 'A-Z'
HELLO
[root@ubuntu huhao123]# cat t.txt
hello
[root@ubuntu huhao123]# echo hello |tr 'a-z' 'A-Z'|tee t.txt 
HELLO
[root@ubuntu huhao123]# cat t.txt
HELLO

[root@ubuntu huhao123]# echo hello |tr 'a-z' 'A-Z'|tee -a t.txt 
HELLO
[root@ubuntu huhao123]# cat t.txt
HELLO
HELLO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值