一个程序运行就必须要有指令和数据或者说数据结构和算法。程序处理的数据来源和处理后存放在哪,是程序员必须要考虑额问题。每个程序都有读入数据和输出数据的需求,但是为了便捷,程序允许缺省输入和输出,也就是使用默认的输入输出。一般称之为标准输入和标准输出。

对于用户来说,访问文件是通过文件名来进行的,但对于内核来说则是一个非零整数,这个数字叫做文件描述符(file descriptor,fd),打开已存在的文件或新建一个文件时,内核会返回一个文件描述符,读写文件也需要使用文件描述符来指定带读写的文件。

注意:文件描述符和inode号是有区别的,inode号是文件系统创建时就已经确定的,当创建一个新的文件或目录时,系统从inode表中选出一个空闲的inode号来唯一标识这个文件,并将文件的数据块位置存在inode里,当许多用户对同一个文件进行操作时,内核将为每位用户分配一个文件描述符,即一个文件可能对应多个文件描述符。

具体的Linux文件系统原理可以参考:

https://www.ibm.com/developerworks/cn/linux/l-linux-filesystem/

https://akaedu.github.io/book/ch29s03.html

https://www.ibm.com/developerworks/cn/linux/l-vfs/  

标准输入的文件描述符是0,标准输出是1,标准错误输出是2

I/O重定向:改变标准位置

重定向支持的操作符有三种:

>:标准输出重定向,可以输出到指定的文件,但会覆盖文件内容,>>则是在文件内容的后面追加新内容

2>:重定向错误到文件,和>类似,2>>表示追加

<:输出重定向

set -C:禁止重定向到文件时覆盖已存在的文件,只对当前shell有效

set +C:撤销禁用覆盖

[root@localhost testdir]# ajf 2> afi
[root@localhost testdir]# set -C
[root@localhost testdir]# ajf 2> afi
-bash: afi: cannot overwrite existing file
[root@localhost testdir]# ajf 2> a
[root@localhost testdir]# ajf 2> a
-bash: a: cannot overwrite existing file

可以将标准输出和标准错误输出分别重定向到不同文件

[root@localhost testdir]# ll
total 8
-rw-r--r--. 1 root root 32 Jul 31 09:50 
a-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
[root@localhost testdir]# ll a afi mage > f1 2> f2
[root@localhost testdir]# cat f1 
-rw-r--r--. 1 root root 32 Jul 31 09:50 a
-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
[root@localhost testdir]# cat f2
ls: cannot access mage: No such file or directory

如果要将输出和错误同时写入一个文件,也可以用更简便的写法

[root@localhost testdir]# cat f1 f2 f3 &> f4
[root@localhost testdir]# cat f4
-rw-r--r--. 1 root root 32 Jul 31 09:50 a
-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
ls: cannot access mage: No such file or directory
cat: f3: No such file or directory

或者用下面的老写法

[root@localhost testdir]# cat f1 f2 f3 > f5 2>&1
[root@localhost testdir]# cat f5
-rw-r--r--. 1 root root 32 Jul 31 09:50 a
-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
ls: cannot access mage: No such file or directory
cat: f3: No such file or directory

同理,&>>表示追加

[root@localhost testdir]# cat f1 f2 f3 >> f5 2>&1
[root@localhost testdir]# cat f1 f2 f3 &>> f4

也可以合并多个命令的输出

[root@localhost testdir]# (cat f4;ls ) > f3
[root@localhost testdir]# cat f3
-rw-r--r--. 1 root root 32 Jul 31 09:50 a
-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
ls: cannot access mage: No such file or directory
cat: f3: No such file or directory
-rw-r--r--. 1 root root 32 Jul 31 09:50 a
-rw-r--r--. 1 root root 32 Jul 31 09:48 afi
ls: cannot access mage: No such file or directory
cat: f3: No such file or directory
a
afi
f1
f2
f3
f4
f5

可以看到,先创建了重定向的文件,在执行前面的内容,然后将输出写入文件

[root@localhost testdir]# rm -rf *
[root@localhost testdir]# ll        #此时没有文件
total 0
[root@localhost testdir]# ll > file1      #ll当前空目录并重定向到file1
[root@localhost testdir]# cat file1      #然而file1的内容不为空,显示了它自己的信息,并且它的大小是0
total 0
-rw-r--r--. 1 root root 0 Jul 31 10:05 file1

输入重定向:<

使用<可以配合cat创建并写入文件

[root@localhost testdir]# cat <<eof
> aaa
> bbb
> ccc
> 
> eof
aaa
bbb
ccc

必须是<<,eof为定义的结束标志,可以是任意字符,也可以将输出重定向到文件

[root@localhost testdir]# cat >> aaa <<eof
> welcome to the new world!
> eof
[root@localhost testdir]# cat aaa
welcome to the new world!

tr命令:转换或输出字符串

语法:tr [OPTIONS] set1 [set2]

tr复制标准输入到标准输出,并且执行转化、挤压重复字符串、删除字符串、先删除然后将输出再挤压重复的字符

-c,-C,--complement 取字符集的子集

-d,--delete 删除属于第一字符集的字符

-s,--squeeze-repeats 把连续且重复的字符用一个表示

-t,--truncate-set1 将第一个字符集对应的字符转化为第二个字符集对应的字符

 mail 发送那个信息:

mail -s NAME WHO

管道:

将命令1的标准输出发送给命令2的标准输入,以此类推

标准错误默认不能通过管道传输,可用2>&1或|&实现

最后一个命令会在当前shell进程的子shell进程中执行

重定向到多个目标:tee

[root@localhost testdir]# ls |tee f1 
aaa
asd
file1
[root@localhost testdir]# cat f1
aaa
asd
file1

tee会将命令的输出重定向到标准输出和一个文件