linux存在的文件重定向 (linux给文件赋权可能会出现的问题)

话接上回。。。(忘记了的可以回顾一下上集)

2.8 创建空文件和刷新时间

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

格式:

touch  + 选项 + 文件名

选项说明:

  • -a 仅改变 atime和ctime
  • -m 仅改变 mtime和ctime
  • -t [[CC]YY]MMDDhhmm[.ss] 指定atime和mtime的时间戳
  • -c 如果文件不存在,则不予创建

案例:

[root@nginx test]# touch win.txt
[root@nginx test]# ll
总用量 12
-rw-r--r--. 1 root root    4 6月  22 21:13 win.txt
[root@nginx test]# ll /etc/issue
-rw-r--r--. 1 root root 23 4月  29 2018 /etc/issue
[root@nginx test]# stat /etc/issue
  文件:"/etc/issue"
  大小:23        	块:8          IO 块:4096   普通文件
设备:fd00h/64768d	Inode:67147067    硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
环境:system_u:object_r:etc_t:s0
最近访问:2026-03-15T22:38:58+00:00.422999978 +0800
最近更改:2026-03-15T22:38:58+00:00.000000000 +0800
最近改动:2026-03-15T22:38:58+00:00.638690349 +0800
创建时间:-
[root@nginx test]# date
2023年 06月 23日 星期五 11:59:07 CST
[root@nginx test]# touch `date -d "-1 day" +%F_%T`.log
[root@nginx test]# ls
2023-06-22_11:59:39.log
[root@nginx test]# touch $(date -d "1 year" +%F_%T).log
[root@nginx test]# ls
2023-06-22_11:59:39.log  2024-06-23_12:00:06.log

2.9 复制文件和目录

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

格式:

cp +[选项] +源文件 +目标文件

选项:

  • -a:相当于 -d、-p、-r 选项的集合
  • -d:如果源文件为软链接(对硬链接无效),则复制出的目标文件也为软链接;
  • -i:询问,如果目标文件已经存在,则会询问是否覆盖;
  • -l:把目标文件建立为源文件的硬链接文件,而不是复制源文件;
  • -s:把目标文件建立为源文件的软链接文件,而不是复制源文件;
  • -p:复制后目标文件保留源文件的属性(包括所有者、所属组、权限和时间);
  • -r:递归复制,用于复制目录;
  • -u:若目标文件比源文件有差异,则使用该选项可以更新目标文件,此选项可用于对文件的升级和备用。

注意:源文件可以有多个,但这种情况下,目标文件必须是目录才可以。

软链接就像win系统的快捷方式,硬链接则是通过llinux文件系统的 inode 号产生的新文件名。不管是复制软链接还是硬链接,都不是复制源文件。

2.9.1 复制文件:cp -i

案例:

#创建文件
[root@nginx test]# touch ts.txt   

# 把ts.txt“不改名”复制到 /tmp/ 目录下
[root@nginx test]# cp  ts.txt /tmp     

 # 把ts.txt“改名”复制到 /tmp/ 目录下,通过cp可以对源文件复制的同时并重命名到目标目录
[root@nginx test]# cp ts.txt /tmp/ts1.txt   
[root@nginx test]# ls /tmp/
ts1.txt  ts.txt 
[root@nginx test]#

如果复制的目标位置已经存在同名的文件,则会 提示是否覆盖因为 cp 命令默认执行的是 “cp -i” 的别名

案例:

[root@nginx test]# cp ts.txt /tmp/
cp:是否覆盖"/tmp/ts.txt"?      #不想覆盖可以通过键盘选择no或者ctrl+c进行中断

2.9.2 复制目录:cp -r

复制目录只需使用 “cp -r” 选项即可

案例:

#创建测试目录
[root@nginx test]# mkdir ts

#目录不改名复制
[root@nginx ~]# cp -r /root/test/ts /tmp/
[root@nginx ~]# ls /tmp/
ts  ts1.txt  ts.txt  

2.9.2.3 复制软链接文件:cp -d

源文件不是一个普通文件,而是一个软链接文件的时候

#创建软链接测试文件
[root@nginx test]# ln -s ts.tx /tmp/ts_slink

# 源文件本身是一个软链接文件
[root@nginx test]# ll /tmp/ts_slink 
lrwxrwxrwx. 1 root root 5 6月  23 15:53 /tmp/ts_slink -> ts.tx

# 复制软链接文件,加入"-d"选项
[root@nginx test]# cp -d /tmp/ts_slink /tmp/ts_slink1
[root@nginx test]# ll /tmp/
总用量 0
lrwxrwxrwx. 1 root root 5 6月  23 15:53 ts_slink -> ts.tx
lrwxrwxrwx. 1 root root 5 6月  23 16:00 ts_slink1 -> ts.tx

2.10 移动和重命名文件

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

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

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

格式:

mv  [选项]  源文件或者目录  目标文件/目录或者目标位置

常用选项:

  • -i 交互式
  • -f 强制
  • -b 目标存在,覆盖前先备份
#移动a.txt文件并改名为b.txt,在同一个目录下操作,即/test目录下
[root@nginx test]#mv  a.txt  b.txt

#移动a.txt文件到 /tmp目录下,文件名不变
[root@nginx test]#mv  a.txt  /tmp/a.txt

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

格式:

rename [选项]... 模式 替换 列表

选项:

  • -v, --verbose:显示更改的文件名;
  • -n, --no-act:仅显示要更改的文件名,不执行实际的更改;
  • -f, --force:强制覆盖已存在的文件;
  • -h, --help:显示帮助信息。

将当前目录下所有以.txt结尾的文件名替换为.text:

[root@nginx test]# rename 's/\.txt$/\.text/' *.txt

将当前目录下所有以test开头的文件名替换为tt:

[root@nginx test]# rename 's/^test/tt/' test*
#为所有的conf文件加上.bak后缀:
rename  'conf'  'conf.bak'  f*
  
#去掉所有的bak后缀:
rename  '.bak'  ''  *.bak

2.11 删除文件

使用 rm 命令可以删除文件

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

格式:

rm 【选项 】 文件名

常用选项:

  • -i 交互式
  • -f 强制删除
  • -r 递归
  • --no-preserve-root 删除/
#删除/test目录下的test1.txt 文件
[root@nginx test]# rm -rf  test1.txt

2.12 目录操作

2.12.1 mkdir 目录创建

格式

mkdir [选项]... 目录...

常见选项:

  • -p: 存在于不报错,创建多级目录
  • -v: 显示详细创建过程
  • -m MODE: 创建目录时直接指定权限

案例:

#创建test目录
[root@nginx ~]#mkdir test
 #创建多级目录
[root@nginx ~]#mkdir -p /tmp/te1/te2/te3..../N

2.12.2 rmdir删除空目录

常见选项:

  • -p 递归删除父空目录
  • -v 显示详细信息

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

案例:

#多层目录
[root@nginx tmp]# ll  te/te1/te2/1.txt 
-rw-r--r--. 1 root root 0 6月  23 18:41 te/te1/te2/1.txt

#只能删空目录
[root@nginx tmp]# rmdir te/
rmdir: 删除 "te/" 失败: 目录非空

#-p递归删除多层空目录
[root@nginx tmp]# rmdir -p te/te1/te2/
[root@nginx tmp]#

3 文件元数据和节点表结构

3.1 inode表结构

每个文件的属性信息,比如:文件的大小,时间,类型等,称为文件的元数据(meta data)。这此元数据是存放在inode(index node)表中。node 表中有很多条记录组成,第一条记录对应的存放了一个文件的元数据信息

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

  • inode number 节点号
  • 文件类型
  • 权限
  • UID
  • GID
  • 链接数(指向这个文件名路径名称个数)
  • 该文件的大小和不同的时间戳
  • 指向磁盘上文件的数据块指针
  • 有关文件的其他数据

目录

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

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

cp和inode

cp 命令:

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

rm和inode

rm 命令:

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

mv和inode

  • 如果mv命令的目标和源在相同的文件系统,作为mv 命令

用新的文件名创建对应新的目录项

删除旧目录条目对应的旧的文件名

不影响inode表(除时间戳)或磁盘上的数据位置:没有数据被移动

  • 如果目标和源在一个不同的文件系统, mv相当于cp和rm

3.2 硬(hard)链接

硬链接本质上就给一个文件起一个新的名称,实质是同一个文件

硬链接特性

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

格式:

ln  文件名  文件链接名

3.3 符号 symbolic (或软 soft)链接

一个符号链接指向另一个文件,就像 windows 中快捷方式,软链接文件和原文件本质上不是同一个文件

软链接特点

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

格式:

ln  -s  文件名  文件链接名

案例:

#绝对路径
[root@nginx ~]#ln -s /tmp/dir /tmp/dirlink
#相对路径
[root@nginx ~]# cd /tmp

[root@nginx tmp]#ln -s ../tmp/dir  /root/dirlink
rm -rf /tmp/dirlink  #删除软链接本身,不会删除源目录内容
rm -rf /tmp/dirlink/  #删除源目录的文件,不会删除链接文件

#查看链接文件指向的原文件
readlink /tmp/dirlink

4 IO 重定向和管道

4.1 标准输入和输出

程序:指令+数据

读入数据:Input

输出数据:Output

打开的文件都有一个fd: file descriptor (文件描述符)

Linux给程序提供三种 I/O 设备

  • 标准输入(STDIN) -0 默认接受来自终端窗口的输入
  • 标准输出(STDOUT)-1 默认输出到终端窗口
  • 标准错误(STDERR) -2 默认输出到终端窗口

案例:文件描述符

[root@nginx tmp]# ll /dev/std*
lrwxrwxrwx. 1 root root 15 6月  23 11:33 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 6月  23 11:33 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 6月  23 11:33 /dev/stdout -> /proc/self/fd/1

[root@nginx tmp]# ll /proc/self/fd/*
ls: 无法访问/proc/self/fd/255: 没有那个文件或目录
ls: 无法访问/proc/self/fd/3: 没有那个文件或目录
lrwx------. 1 root root 64 6月  23 19:40 /proc/self/fd/0 -> /dev/pts/0
lrwx------. 1 root root 64 6月  23 19:40 /proc/self/fd/1 -> /dev/pts/0
lrwx------. 1 root root 64 6月  23 19:40 /proc/self/fd/2 -> /dev/pts/0
[root@nginx tmp]#

4.2 I/O重定向 redirect

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

4.2.1 标准输出和错误重新定向

STDOUT和STDERR可以被重定向到指定文件,而非默认的当前终端

格式:

命令 操作符号 文件名

支持的操作符号包括:

1> 或 >  :把STDOUT重定向到文件
2>     :把STDERR重定向到文件
&>   :把标准输出和错误都重定向
>&         :和上面功能一样,建议使用上面方式

以上如果文件已存在,文件内容会被覆盖

set -C  禁止将内容覆盖已有文件,但可追加, 利用 >| 仍可强制覆盖
set +C  允许覆盖,默认

追加 “>>”

可以在原有内容基础上,追加内容

把输出和错误重新定向追加到文件

>> 追加标准输出重定向至文件
2>> 追加标准错误重定向至文件

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

命令> /路径/file.out 2> /路径/error.out

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

&> 覆盖重定向
&>> 追加重定向
命令 > /路径/file.out  2>&1 (顺序很重要)
命令 >> /路径/file.out  2>&1

合并多个程序

(命令1;命令2......) 或者{命令1;命令2;....; }合并多个程序的STDOUT

案例:

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

案例:标准错误重定向

[root@nginx ~]#rm /tmp/f1.log 2> /tmp/all.log
 [root@nginx tmp]# cat all.log 
rm: 无法删除"/tmp/f1.log": 没有那个文件或目录

案例:合并多个命令的结果至一个文件中

#打印显示日历2022和2023年的重定向到all.txt文件
[root@nginx ~]#( cal 2022 ; cal 2023 ) > all.txt

#ls列出当前的文件或者目录,显示主机名重定向到all.log文件
[root@nginx ~]#{ ls;hostname; } > /tmp/all.log

案例:清除大文件

#两个都是把“空”输出到你想清除文件里面
[root@nginx ~]#cat /dev/null >/tmp/file.log
[root@nginx ~]#> /tmp/file.log

案例:分别重定向

#把ls列出/tmp目录下的文件或者目录标准正确输出到stdout.log文件
 接着ls列出一个不存在的/xxx目录,把显示错误的内容标准错误输出到stderr.log文件
[root@nginx ~]#ls /tmp/ /xxx > stdout.log 2> stderr.log

4.2.2 标准输入重定向

从文件中导入STDIN,代替当前终端的输入设备,使用 < 来重定向标准输入

某些命令能够接受从文件中导入的STDIN

4.2.2.1 标准输入重定向

利用“<” 可以将标准输入重定向

案例:

[root@nginx ~]#echo 2^2 > bc.log
[root@nginx ~]#cat bc.log
2^2
[root@nginx ~]#bc < bc.log
4

4.3 管道

4.3.1 管道

管道(使用符号“|”表示)用来连接多个命令

格式:

命令1 | 命令2 | 命令3 | …

功能说明:

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

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

命令1 2>&1 | 命令2

命令1 |& 命令2

案例:

[root@nginx tmp]# ps -ef |grep nginx
root 1713 1 0 20:35 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 1715 1713 0 20:35 ? 00:00:00 nginx: worker process
root 1717 1326 0 20:35 pts/0 00:00:00 grep --color=auto nginx


[root@nginx tmp]# ls /tmp /xxx | tr 'a-z' 'A-Z'
ls: 无法访问/xxx: 没有那个文件或目录
/TMP:
ALL.LOG
ALL.TXT
FILE.LOG
TS1.TXT
TS_SLINK
[root@nginx tmp]# ls /tmp /xxx 2>&1 | tr 'a-z' 'A-Z'
LS: 无法访问/XXX: 没有那个文件或目录
/TMP:
ALL.LOG
ALL.TXT
FILE.LOG
TS1.TXT
TS_SLINK
[root@nginx tmp]# ls /tmp /xxx |& tr 'a-z' 'A-Z'
LS: 无法访问/XXX: 没有那个文件或目录
/TMP:
ALL.LOG
ALL.TXT
FILE.LOG
TS1.TXT
TS_SLINK
[root@nginx tmp]# 

聪明如你,想必学到了不少。。。

纸上学来终觉浅,在多练几遍又有不一样的领悟!