shell:文件描述符与重定向
文件描述符是与输入和输出流相关联的整数,最广为人知的文件描述符是标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。默认情况下,正常输出(stdout)和错误信息(stderr)都会显示在屏幕上。脚本可以使用大于号将输出重定向到文件中。
文章目录
- 文件描述符
- 将一个命令的输入发送给另一个命令
- 重定向stdin
- 重定向stdout
- 重定向stderr
- 自定义文件描述符
文件描述符
文件描述符是与某个打开的文件或数据流相关联的整数。文件描述符0、1以及2是系统预留的。
- 0 —— stdin (标准输入)。
- 1 —— stdout(标准输出)。
2 —— stderr(标准错误)。
$ cat /dev/stdin
将/dev/stdin作为输出文件名来代替stdin,/dev/stderr代表标准错误,
/dev/stdout代表标准输出。这些特殊的设备文件分别对应stdin、stderr和stdout
将一个命令的输入发送给另一个命令
Unix shell脚本可以轻松地将多个命令组合起来生成输出。一个命令的输出可以作为另一个命令的输入。
命令输入通常来自于stdin或参数。输出可以发送给stdout或stderr。当我们组合多个命令时,通常将stdin用于输入,stdout用于输出
在这种情况下,这些命令被称为过滤器(filter)。
- 方法1:使用管道
我们使用管道(pipe)连接每个过滤器,管道操作符是|。
cmd1 | cmd2 | cmd3
cmd1的输出传递给cmd2,cmd2的输出传递给cmd3,最终的输出(来自cmd3)会出现在显示器中或被导入某个文件
$ ls | cat -n > out.txt #ls(列出当前目录内容)的输出被传给cat -n,后者为通过stdin所接收到的输入内容加上行号,然后将输出重定向到文件out.txt
- 方法2:将命令序列的输出赋给变量
子shell法:cmd_output=$(COMMANDS)
$ cmd_output=$(ls | cat -n)
$ echo $cmd_output反标记:cmd_output=
COMMANDS
$ cmd_output=
ls | cat -n
$ echo $cmd_output
备注:子shell法的用法
- 将一个命令的输入发送给另一个命令
利用子shell生成一个独立的进程利用子shell生成一个独立的进程
子shell本身就是独立的进程,因此可以使用()操作符来定义一个子shell。当命令在子shell中执行时,不会对当前shell造成任何影响;所有的改变仅限于该子shell内。$ pwd
/home/ocean/workspaces/shell
$ (cd /bin; ls)
bash dir lessecho nisdomainname red
$ pwd
/home/ocean/workspaces/shell
重定向stdin
(1)< 从文件中读取内容
$ cat
thie is a test
thie is a test
a sohow,lcdw
a sohow,lcdw
$ cat < testfile
$ sudo echo "echo 重定向stdin" > file
$ bash < file // 将文件重定向到命令
重定向stdin
重定向stdout
将输出文件重定向到一个文本中【追加/截断】
- “>”表示将文本保存到文件中,如果文件中已经有了内容,>会先清空内容再添加。
“>>”表示文本追加
$ cat temp.txt
cat: temp.txt: No such file or directory
$ echo “This is a sample text 1” > temp.txt
$ cat temp.txt
This is a sample text 1
$ echo “This is sample text 2” >> temp.txt
$ cat temp.txt
This is a sample text 1
This is sample text 2
$ echo “This is a sample text 1” > temp.txt
$ cat temp.txt
This is a sample text 1
重定向操作符(>和>)可以将输出发送到文件中,而不是终端。
- “>”和>>两者都可以将文本重定向到文件,但是前者会先清空文件,然后再写入内容,而后者会将内容追加到现有文件的尾部
- 默认情况下,重定向操作符针对标准输出
处理错误时,来自stderr的输出被倾倒入/dev/null中。/dev/null是一个特殊的设备文件,它会丢弃接收到的任何数据。null设备通常也被称为黑洞,因为凡是进入其中的数据都将一去不返。
如果你不想看到或保存错误信息,那么可以将stderr的输出重定向到/dev/null,保证一切都会被清除得干干净净。
重定向stderr
当一个命令发生错误并退回时,它会返回一个非0的退出状态;而当命令成功完成后,它会返回为0的退出状态。退出状态可以从特殊变量$?中获得(在命令结束之后立刻运行echo $?,就可以打印出退出状态)。
$ ls +
ls: cannot access '+': No such file or directory
$ echo $?
2
stderr会默认输出到品目上
使用>重定向stderr到文本
$ ls + > out.txt # 定位失败
ls: cannot access '+': No such file or directory
$ cat out.txt
$ ls + 2> out.txt # 定位成功
$ cat out.txt
ls: cannot access '+': No such file or directory
重定向stderr和stdout
$ echo A1 > a1
$ echo A2 > a2
$ echo A3 > a3
$ chmod 000 a1 #清除所有权限
$ cat a*
cat: a1: Permission denied #属于stderr信息
A2
A3
(1)stderr重定向到一个文件中,同时将stdout信息发送到终端。
$ cat a* 2> err.txt # stderr被重定向到err.txt
A2
A3
$ cat err.txt
cat: a1: Permission denied
(2) 将stdout和stderr重定向到两个不同的文件中
$ cat a* 2> stderr.txt 1>stdout.txt
$ cat stderr.txt
cat: a1: Permission denied
$ cat stdout.txt
A2
A3
备注:
>等同于1>
>>等同于1>>
(3) stdout和stderr重定向到同一个文件中
$ cat a* &> alloutput.txt
$ cat alloutput.txt
cat: a1: Permission denied
A2
A3
stdout是单数据流,可以被重定向到文件或者通过管道传入其他程序。但是无法同时重定向到文件和传入其他程序
(4)想要将数据重定向到文件,并且提供一份重定向数据的副本作为管道中后续命令的stdin:
command | tee FILE1 FILE2 | otherCommand
$ cat a* | tee out.txt | cat -n
cat -n 命令 接收stdin中的数据并加上行号然后写入stdout
cat: a1: Permission denied
1 A2
2 A3
$ cat out.txt
A2
A3tee -a
默认情况下,tee会将文件覆盖,但是tee -a可以追加
$ cat a* | tee out.txt | cat -n
cat: a1: Permission denied1 A2
2 A3
$ cat out.txt
A2
A3
$ cat a* | tee -a out.txt | cat -n
cat: a1: Permission denied1 A2
2 A3
$ cat out.txt
A2
A3
A2
A3
自定义文件描述符
文件描述符是一种用于访问文件的抽象指示器。存取文件离不开被称为“文件描述符”的特殊数字。0,1,2是系统保留的
exec命令创建全新的文件描述符。
(1) 创建一个用于读取文件的文件描述符【一次性消耗品】
<:将文件读入stdin
$ echo this is a test line > input.txt
$ exec 3<input.txt #使用文件描述符3打开并读取文件, 3这个文件描述符只能使用一次
$ cat<&3
this is a test line
$ cat<&3 #如果要再次读取,我们就不能继续使用文件描述符3了[因为stdin是单向数据流],而是需要用exec重新创建一个新的文件描述符3/4/5/6 。
$ cat input.txt
this is a test line
(2)创建一个用于写入(截断也就是清空模式)的文件描述符
“>”:将文件截断写入 failure
(3)创建一个用于写入(追加模式)的文件描述符
$ exec 5>>input.txt
$ echo appended line >&5
$ cat input.txt
appended line
$ echo appended line >&5
$ cat input.txt
appended line
appended line
参考:
还没有评论,来说两句吧...