Linux重定向:从一句代码加深理解
-
1 重定向迷思:
touch test.txt echo hello > test.txt (cat; echo apple > /dev/stdin; cat) < test.txt
以上命令执行完毕后,标准输出流会输出
hello
,而没有apple
,为什么呢?
这个要从重定向的机制开始理解。Linux系统是以文件系统为核心理念的系统,即"一切都是文件"。而流也不例外,比如标准流有stdin
、stdout
和stderr
。这三者均有file descriptor
分别为0、1、2。而它们对应的文件均在/dev
目录下,分别为/dev/stdin
、/dev/stdout
和/dev/stderr
。
重定向的本质是将某个file descriptor
所操作的文件修改为命令中提供的文件。例如:ls -alF 2>/dev/null
就是将标准错误流
stderr
所写入的文件改为/dev/null
。
那么回到一开始的问题,为什么标准输出流只输出hello
呢?
在执行cat
的时候,标准输入流就已经指向了test.txt
,因此直接从标准输入流中读入内容,即为hello
。
但是,要注意到一个细节,和C语言一样,文件的读写是有位置的,即file position
,经过第一个指令后,标准输入流的file descriptor
已经读了6个字节了,即"hello"以及一个echo
默认自带的换行符。此时,echo
将字符串"apple"覆盖到/dev/stdin
中,但由于已经读了6个字符了,此时文件位置指向"apple"尾部的EOF
。
最后再执行cat
,读取/dev/stdin
的最后一个字符——EOF
,该字符在cat
下不会打印任何字符,只是终止cat
。2 重定向的语法:
一般来说,重定向有两种语法:为
file descriptor
打开一个新的文件,或者将某个file descriptor
修改为与另一个同类型修饰符操作同一个文件,简称复制修饰符(Duplicate Descriptor
)[n] > file
:为修饰符n
打开一个文件供其写入。若不给出n
则默认为标准输出流
[n] < file
: 为修饰符打开一个文件供其读取。若不给出n
则默认为标准输入流[n] >& m
: 将修饰符n
设置为与m
操作对象一致。默认为标准输出流。
[n] <& m
: 默认为标准输入流。