一个程序运行就必须要有指令和数据或者说数据结构和算法。程序处理的数据来源和处理后存放在哪,是程序员必须要考虑额问题。每个程序都有读入数据和输出数据的需求,但是为了便捷,程序允许缺省输入和输出,也就是使用默认的输入输出。一般称之为标准输入和标准输出。
对于用户来说,访问文件是通过文件名来进行的,但对于内核来说则是一个非零整数,这个数字叫做文件描述符(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:撤销禁用覆盖
[[email protected] testdir]# ajf 2> afi [[email protected] testdir]# set -C [[email protected] testdir]# ajf 2> afi -bash: afi: cannot overwrite existing file [[email protected] testdir]# ajf 2> a [[email protected] testdir]# ajf 2> a -bash: a: cannot overwrite existing file
可以将标准输出和标准错误输出分别重定向到不同文件
[[email protected] 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 [[email protected] testdir]# ll a afi mage > f1 2> f2 [[email protected] 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 [[email protected] testdir]# cat f2 ls: cannot access mage: No such file or directory
如果要将输出和错误同时写入一个文件,也可以用更简便的写法
[[email protected] testdir]# cat f1 f2 f3 &> f4 [[email protected] 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
或者用下面的老写法
[[email protected] testdir]# cat f1 f2 f3 > f5 2>&1 [[email protected] 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
同理,&>>表示追加
[[email protected] testdir]# cat f1 f2 f3 >> f5 2>&1 [[email protected] testdir]# cat f1 f2 f3 &>> f4
也可以合并多个命令的输出
[[email protected] testdir]# (cat f4;ls ) > f3 [[email protected] 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
可以看到,先创建了重定向的文件,在执行前面的内容,然后将输出写入文件
[[email protected] testdir]# rm -rf * [[email protected] testdir]# ll #此时没有文件 total 0 [[email protected] testdir]# ll > file1 #ll当前空目录并重定向到file1 [[email protected] testdir]# cat file1 #然而file1的内容不为空,显示了它自己的信息,并且它的大小是0 total 0 -rw-r--r--. 1 root root 0 Jul 31 10:05 file1
输入重定向:<
使用<可以配合cat创建并写入文件
[[email protected] testdir]# cat <<eof > aaa > bbb > ccc > > eof aaa bbb ccc
必须是<<,eof为定义的结束标志,可以是任意字符,也可以将输出重定向到文件
[[email protected] testdir]# cat >> aaa <<eof > welcome to the new world! > eof [[email protected] 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
[[email protected] testdir]# ls |tee f1 aaa asd file1 [[email protected] testdir]# cat f1 aaa asd file1
tee会将命令的输出重定向到标准输出和一个文件
练习:
1、将/etc/issue文件的内容转换为大写保存到/tmp/issue.out文件中
[[email protected] ~]# tr [a-z] [A-Z] < /etc/issue > /tmp/issue.out [[email protected] ~]# cat /tmp/issue.out \S KERNEL \R ON AN \M
或者
[[email protected] ~]# tr ‘[:lower:]‘ ‘[:upper:]‘ < /etc/issue > /tmp/issue.out.bak [[email protected] ~]# cat /tmp/issue.out.bak \S KERNEL \R ON AN \M
2、将当前系统登录用户信息转换为大写后保存至/tmp/who.out文件中
[[email protected] ~]# w |tr ‘[:lower:]‘ ‘[:upper:]‘ > /tmp/who.out [[email protected] ~]# cat /tmp/who.out 10:54:38 UP 1:23, 2 USERS, LOAD AVERAGE: 0.00, 0.01, 0.05 USER TTY FROM [email protected] IDLE JCPU PCPU WHAT ROOT PTS/0 10.1.250.91 09:31 6.00S 0.49S 0.02S W ROOT PTS/1 10.1.250.91 09:36 21:10 0.29S 0.26S INFO TR
3、一个Linux用户给root发邮件,邮件标题为help,正文是:Hello,I am 用户名,the system version is here,please help me to check it ,thanks!
操作系统信息
[[email protected] ~]$ mail -s "help" root <<eof > Hello,I am `whoami`,the system version is here,please help me to check it,thanks! > `uname -or` > eof [[email protected] ~]$
[[email protected] ~]# mail Heirloom Mail version 12.5 7/5/10. Type ? for help >N 8 nieda Sun Jul 31 11:01 19/716 "help" & 8 Message 8: From [email protected] Sun Jul 31 11:01:36 2016 Return-Path: <[email protected]> X-Original-To: root Delivered-To: [email protected] Date: Sun, 31 Jul 2016 11:01:36 +0800 To: [email protected] Subject: help User-Agent: Heirloom mailx 12.5 7/5/10 Content-Type: text/plain; charset=us-ascii From: [email protected] (nieda) Status: R Hello,I am nieda,the system version is here,please help me to check it,thanks! 3.10.0-327.el7.x86_64 GNU/Linux
其中`whoami`可以用$USER替换,uname -ar可能信息不全,可以用uname -a或者cat /etc/centos-release
也可以将要发送的信息先写在一个文件里,然后在发送,但是要发送的文件里只能是纯文本,不能有变量和命令。
4、将/root/下文件列表,显示成一行,文件名之间用空格隔开
[[email protected] ~]# ls /root/ |tr ‘\n‘ ‘ ‘ anaconda-ks.cfg Desktop Documents Downloads f1 file1 initial-setup-ks.cfg Music Pictures Public Templates Videos [[email protected] ~]#
5、file1文件的内容为“1 2 3 4 5 6 7 8 9 10”计算出所有数字的总和
[[email protected] testdir]# cat file 1 2 3 4 5 6 7 8 9 10 [[email protected] testdir]# cat file |tr ‘ ‘ ‘+‘|bc 55
6、删除wndows文本文件中的‘^M’字符
[[email protected] testdir]# cat windows.txt a^M bhello^MaMDZZ MDZZ[[email protected] testdir]# file windows.txt windows.txt: ASCII text, with CRLF line terminators
[[email protected] testdir]# hexdump windows.txt 0000000 5e61 0d4d 620a 6568 6c6c 5e6f 614d 444d 0000010 5a5a 0a0d 444d 5a5a 0000018
可以看到^M的二进制是61
[[email protected] testdir]# cat windows.txt |tr -d ^M a bhello aDZZ
7、处理字符串“xt.,| 1 jr#!$mn 2 c*/fe 3 uz 4”,只保留其中的数字和空格
[[email protected] testdir]# cat a xt.,| 1 jr#!$mn 2 c*/fe 3 uz 4 [[email protected] testdir]# tr -c -d ‘[:digit:][:space:]‘ < a 1 2 3 4
8、将PATH变量每个目录显示在独立的一行
[[email protected] testdir]# echo $PATH /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [[email protected] testdir]# echo $PATH|tr ‘:‘ ‘\n‘ /usr/lib64/qt-3.3/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /root/bin
9、删除指定文件的空行
[[email protected] testdir]# cat a hello,wang I am root I have some questions about the linux command need your help if you have time,call me please! eof [[email protected] testdir]# tr -s ‘\n‘ < a hello,wang I am root I have some questions about the linux command need your help if you have time,call me please! eof [[email protected] testdir]#
10、将文件中每个单词(字母)显示在独立的一行,并无空行
[[email protected] testdir]# tr ‘[:blank:][:punct:]‘ ‘\n‘ < word |tr -s ‘\n‘ hello this is the CCTV welcome to listen our news you can look the news happend everywhere at once