在 linux 中一切皆文件,每一个打开的文件或程序都有一个 fd(file descriptor,文件描述符)。
标准输入:来源于 keyboard 即键盘,文件描述符为 0。
标准输出:输出到 monitor 即监视器,文件描述符为 1。
标准错误输出:输出到 monitor 即监视器,文件描述符为 2。
概述
IO 重定向指的是手动改变输入和输出的位置,不使用标准输入和标准输出。
输出重定向
输出重定向分为两类,分别为覆盖输出和追加输出,使用格式如下:
COMMAND > NEW_POS:覆盖输出
COMMAND >> NEW_POS:追加输出
示例
覆盖输出
[root@localhost ~]# ls /etc/ > /tmp/lsetc.out
[root@localhost ~]# cat /tmp/lsetc.out
adjtime
aliases
aliases.db
alternatives
anacrontab
asound.conf
audisp
audit
...
上述操作就是将 ls /etc/
命令的执行结果输出到 /tmp/lsetc.out
文件中。
之所以称之为覆盖输出,是因为如果后续继续通过 >
符号来将其它结果输出到 /tmp/lsetc.out
中,该文件中原有的内容将被覆盖。
追加输出
[root@localhost ~]# ls /var/ >> /tmp/lsetc.out
[root@localhost ~]# cat /tmp/lsetc.out
adjtime
aliases
aliases.db
alternatives
anacrontab
asound.conf
...
上述操作是将 ls /var/
命令的执行结果输出到 /tmp/lsetc.out
文件的尾部,即该文件中原来已有内容不会被覆盖。
禁止覆盖输出
禁止覆盖输出重定向指的是禁止将内容覆盖输出至已有文件中。
覆盖输出明显是一个很危险的操作,因为它会将一个文件原有的内容清除。所以为了避免我们不小心做出难以挽回的操作,可以手动禁止覆盖输出重定向。
禁止操作可以通过命令 set -C
来实现,看如下示例:
[root@localhost ~]# ls /etc/ > /tmp/lsetc.out
-bash: /tmp/lsetc.out: 无法覆盖已存在的文件
对于事先不存在的文件还是可以通过 >
来输出,例:
[root@localhost ~]# ls /etc/ > /tmp/lsetc.out.new
[root@localhost ~]# cat /tmp/lsetc.out.new
adjtime
aliases
aliases.db
alternatives
...
如果想要取消禁止覆盖输出,则可使用 set +C
命令,例:
[root@localhost ~]# set +C
[root@localhost ~]# ls /etc/ > /tmp/lsetc.out
强制覆盖
在上面我们已经知道可以通过 set -C
来禁止覆盖输出,但实际上在禁止覆盖输出的状态下我们还是可以强制覆盖输出,只需要使用 >|
来进行输出即可,例:
[root@localhost ~]# set -C
[root@localhost ~]# ls /etc/ >| /tmp/lsetc.out
错误输出流
先看如下示例:
[root@localhost ~]# ls /etcnotfound/ > /tmp/lsetc.out
ls: 无法访问/etcnotfound/: 没有那个文件或目录
当我们执行的命令本身参数错误时,shell 内部会给我们返回错误信息输出到控制台。
而在上述实例中是将 ls /etcnotfound/
的结果输出到 /tmp/lsetc.out
中,/etcnotfound/
目录不存在,所以出现了错误信息,查看 /tmp/lsetc.out
会发现错误输出信息是没有保存到该文件中的,这是因为错误输出的信息使用的输出流和命令正常执行的输出流不是同一个,可称之为错误输出流。
>
的作用是将命令正常执行的结果输出到指定位置,如果我们需要将错误输出流重定向到指定位置,则可使用 2>
,例:
[root@localhost ~]# ls /etcnotfound/ 2> /tmp/lsetc.out
[root@localhost ~]# cat /tmp/lsetc.out
ls: 无法访问/etcnotfound/: 没有那个文件或目录
而如果命令正常运行时使用的是 2>
错误重定向,那么正常输出内容会使用标准输出流,即输出到终端,而错误重定向指定的文件不会发生改变。
与标准输出流相同,错误输出流如果要使用追加输出,将 2>
改为 2>>
即可。
标准和错误输出流各自定向至不同位置
如果执行一个命令时需同时指定标准输出和错误输出流指向的位置,使用方式如下:
COMMAND > /POS1 2> /POS2
该示例指的是执行 COMMAND
命令时,如果正常输出,则将正常输出流重定向到 /POS1
位置。如果错误输出,则将错误输出流重定向到 /POS2
位置。
合并标准和错误输出流
如果要指定标准输出和错误输出使用同一个输出流,可使用 &>
的方式,使用方式如下:
COMMAND &> /POS
将 COMMAND
命令的执行结果无论是正常还是错误都输出到 /POS
,追加输出只需使用 &>>
即可。
除了上述 &>
这种方式合并输出流,还可以通过引用流地址实现,使用方式如下:
COMMAND > /POS 2> &1
该示例时将 COMMAND
命令的执行结果覆盖输出到 /POS
,而错误输出时直接使用前一步的标准输出流输出,即同样输出到 /POS
。
输入重定向
标准输入位置指的是键盘,如果要手动指定输入位置,可通过 <
指定。
命令补充
tr
tr
命令用来转换或删除字符,看如下示例:
[root@localhost ~]# tr abc ABC
a person
A person
abc
ABC
在该示例中,首先给 tr
命令指定了 2 个参数,参数 1 为 abc
,参数 2 为 ABC
。而 tr
命令需要一个输入流,默认使用标准输入流即键盘。两个参数的作用就是将输入流内容按位置对应把参数 1 中的字符替换为参数 2 中的字符,即 a
替换为 A
,b
替换为 B
,c
替换为 C
。
再看如下示例,将 /etc/fstab
的内容转大写:
[root@localhost ~]# tr a-z A-Z < /etc/fstab
#
# /ETC/FSTAB
# CREATED BY ANACONDA ON TUE MAY 7 17:25:25 2019
...
在上述实例中,通过 <
手动指定了 tr
命令的输入位置为 /etc/fstab
。
tr
命令还可以从给定的输入内容中删除指定字符再输出,只需要使用它的 -d
选项,例:
[root@localhost ~]# tr -d abc
abcdefg
defg
使用输入重定向通常仅指定一个输入流,要指定多个输入流是通过循环实现。
创建文档
在输出重定向中使用 >
是覆盖输出,使用 >>
则是追加输出。而在输入重定向中使用 <
是输入重定向,但和我们想的不一样的是使用 <<
并不是追加输入。<<
的作用其实是创建文档,看如下示例:
[root@localhost ~]# cat << END
> how are you?
> END
how are you?
上述命令的含义是,先通过 <<
来启用创建文档的功能,文档的创建依赖于标准输入,而 END
表示的是输入结束符(结束符可以是任意字符串),最后将 END
结束符之前的内容作为 cat
命令的输入流,最后 cat
命令通过标准输出流输出。
下面我们可以通过这个功能直接创建文档保存到文件,例:
[root@localhost ~]# cat << END > /tmp/heredoc.txt
> hello
> test heredoc
> END
[root@localhost ~]# cat /tmp/heredoc.txt
hello
test heredoc
评论区