shell脚本编程-重定向
计算机最基础的功能是可以提供输入输出操作,常见的输入设备有键盘、鼠标、扫描仪等,对于Linux系统来说,通常以键盘为默认输入设备,又称标准输入设备;
计算机常见的输出设备有显示器、蜂鸣器、打印机等,而Linux系统则以显示器为默认输出设备,又称标准输出设备。
所谓”重定向“,就是将原本应该从标准输入设备(键盘)输入的数据,改由其他文件或设备输入;或将原本应该输出到标准输出设备(显示器)的内容,改而输出到其他文件或设备上.
系统在启动一个进程的同时会为该进程打开三个文件:标准输入(stdin)、标准输出(stdout)、标准错误输出(stderr),分别用文件标识符0、1、2来标识.默认情况下分别为,键盘,显示器,显示器.
I/O重定向可以将任何文件、命令、脚本、程序或脚本的输出重定向到另外一个文件、命令、程序或脚本.
> | 标准输出覆盖重定向:将命令的输出重定向输出到其他文件中 |
>> | 标准输出追加重定向:将命令的输出重定向输出到其他文件中,同时会覆盖文件中的已有的内容 |
>& | 标准输出重定向:将一个标识的输出重定向到另一个标识的输入 |
< | 标准输入重定向:命令将从指定文件中读取输入而不是从键盘输入 |
| | 管道:从一个命令中读取输出并作为另一个命令的输入. |
1.标准输出覆盖重定向:>
使用标准重定向符号可以将原来输出到显示器上的内容重定向到一个文件中
[rhat@localhost ~]$ ls -l total 36 drwxr-xr-x. 3 rhat rhat 4096 Sep 27 06:30 Desktop drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Documents drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Downloads drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Music drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Pictures drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Public drwxrwxr-x. 2 rhat rhat 4096 Sep 27 03:08 shell drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Templates drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Videos [rhat@localhost ~]$ ls -l > ls_rhat.txt [rhat@localhost ~]$ cat ls_rhat.txt total 36 drwxr-xr-x. 3 rhat rhat 4096 Sep 27 06:30 Desktop drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Documents drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Downloads -rw-rw-r--. 1 rhat rhat 0 Sep 28 02:21 ls_rhat.txt drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Music drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Pictures drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Public drwxrwxr-x. 2 rhat rhat 4096 Sep 27 03:08 shell drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Templates drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Videos
如果文件不存在就会创建一个,存在且内容不为空,会删除原来内容然后再写,所以有时候需要判断原文件是否存在.下面查看一个不存在的文件:
[rhat@localhost ~]$ ls -l /usr/noExist > ls_NoExist.txt #也可写成 ls -l /usr/noExist 1> ls_NOExist.txt ,他两是等效的. ls: cannot access /usr/noExist: No such file or directory [rhat@localhost ~]$ cat ls_NoExist.txt #会发现什么也没有, #因为>默认重定向的是标准输出(1) #这次确实标准错误却是错误输出,所以应该写成 2> #eg: [rhat@localhost ~]$ ls -l /usr/noExist 2> ls_NoExist.txt [rhat@localhost ~]$ cat ls_NoExist.txt ls: cannot access /usr/noExist: No such file or directory
如果某命令既有标准输出,又有标准错误输出,可以分别指派不同的标识符到不同的文件中:
[rhat@localhost ~]$ COMMAND 1> stdout.txt 2> stderr.txt
2.标注输出追加重定向:>>
">>" 用法和 ">" 完全一致,不同的只是如果指定的重定向文件存在且不为空,重定向并不会清空源文件内容,而是将命令的输出新增到源文件尾部。如下:
[rhat@localhost ~]$ ls -l /usr/ >> ls_rhat.txt [rhat@localhost ~]$ cat ls_rhat.txt total 40 drwxr-xr-x. 3 rhat rhat 4096 Sep 27 06:30 Desktop drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Documents drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Downloads -rw-rw-r--. 1 rhat rhat 58 Sep 28 02:26 ls_NoExist.txt -rw-rw-r--. 1 rhat rhat 0 Sep 28 02:36 ls_rhat.txt drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Music drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Pictures drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Public drwxrwxr-x. 2 rhat rhat 4096 Sep 27 03:08 shell drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Templates drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Videos total 144 dr-xr-xr-x. 2 root root 45056 Sep 26 04:41 bin drwxr-xr-x. 2 root root 4096 Jun 28 2011 etc drwxr-xr-x. 2 root root 4096 Jun 28 2011 games drwxr-xr-x. 32 root root 4096 Sep 26 06:27 include dr-xr-xr-x. 15 root root 4096 Sep 26 06:32 lib dr-xr-xr-x. 88 root root 40960 Sep 26 04:41 lib64 drwxr-xr-x. 22 root root 12288 Sep 26 04:41 libexec drwxr-xr-x. 14 root root 4096 Sep 27 06:23 local dr-xr-xr-x. 2 root root 12288 Sep 26 04:41 sbin drwxr-xr-x. 171 root root 4096 Sep 26 06:29 share drwxr-xr-x. 4 root root 4096 Sep 26 06:25 src lrwxrwxrwx. 1 root root 10 Sep 26 06:25 tmp -> ../var/tmp
3.标识输出重定向:>&
标识重定向的作用是将一个标识的输出重定向到另一个标识的输入,比如想将标准输出和标准错误同时输出到同一个文件:
[rhat@localhost ~]$ COMMAND > stdout_stderr.txt 2>&1
以上表示将标准输出到stdout_stderr.txt,如果有标准错误输出也同时重定向到该文件中.
eg:
[rhat@localhost home]$ find / -type f -name *.txt find: `/var/cache/hald': Permission denied /usr/lib64/python2.6/site-packages/simplejson-2.0.9-py2.6.egg-info/top_level.txt /usr/lib64/python2.6/site-packages/simplejson-2.0.9-py2.6.egg-info/dependency_links.txt /usr/lib64/python2.6/site-packages/rhsm-1.1.8-py2.6.egg-info/SOURCES.txt .... /usr/share/doc/ivtv-firmware-20080701/license-end-user.txt /usr/share/doc/ivtv-firmware-20080701/license-oemihvisv.txt /usr/share/doc/obexd-0.19/client-api.txt
以上包含错误输出也包含标准输出,可以用如下的方式来进行分离:
[rhat@localhost home]$ find / -type f -name *.txt > std_out.txt 2> stderr.txt
当然错误输出可能并不关心,我们可以将标准错误输出到/dev/null 中,系统会将任何输出到该设备的内容全部删除.
4.标准输入重定向:<
标准输入重定向将原本应从标准输入设备中读取的内容转由文件内容输入,也就是将文件内容写入标准输入中.例如:
[rhat@localhost ~]$ vim fruit01.txt banana apple carrot [rhat@localhost ~]$ sort < fruit01.txt #是linux中一个排序的命令. apple banana carrot
5.管道:|
管道也是一种重要的I/O重定向方法,就是将一个命令的输出作为另一个命令的输入,例如:
[rhat@localhost ~]$ cat fruit01.txt banana apple carrot [rhat@localhost ~]$ cat fruit01.txt | sort #cat命令的输出冲顶想到sort命令中 apple banana carrot
exec是Shell的内建命令,执行这个命令时系统不会启动新的Shell,而是用要被执行的命令替换当前的Shell进程.下表为exec的用法.
exec <file | 将file文件中的内容作为exec的标准输入 |
exec >file | 将file文件作为标准输出 |
exec 3<file | 指定文件标识符 |
exec 3<&- | 关闭文件标识符 |
exec 3>file | 将写入指定文件标识符的内容写入指定文件(这里的文件是file) |
exec 4<&3 | 创建文件标识符3的拷贝4 |
1.将file文件中的内容作为exec的标准输入.
系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变.所以exec并不会创建新的进程.只是替换了原来进程上下文的内容.
[rhat@localhost ~]$ bash #开启一个新的Shell,不启动新的shell,根shell将最终关闭. [rhat@localhost ~]$ cat command.txt #查看文件中都有哪些命令 echo "Hello , I'am a echo command" ls -l [rhat@localhost ~]$ exec <command.txt #将文件作为本shell的标准输入 [rhat@localhost ~]$ echo "Hello , I'am a echo command" #执行echo Hello , I'am a echo command [rhat@localhost ~]$ ls -l #执行ls -l total 44 -rw-rw-r--. 1 rhat rhat 41 Sep 28 03:24 command.txt drwxr-xr-x. 3 rhat rhat 4096 Sep 27 06:30 Desktop drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Documents drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Downloads -rw-r--r--. 1 rhat rhat 20 Sep 28 03:08 fruit01.txt drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Music drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Pictures drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Public drwxrwxr-x. 2 rhat rhat 4096 Sep 27 03:08 shell drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Templates drwxr-xr-x. 2 rhat rhat 4096 Sep 26 00:46 Videos [rhat@localhost ~]$ exit #文件中的命令执行完毕,退出. 回到上一层shell. [rhat@localhost ~]$ #根Shell.
2.将file文件作为标准输出.
利用exec可将标准输出全部重定向到某个文件中。
[rhat@localhost ~]$ exec >out01.txt #将shell的标准输出重定向到out01.txt中. [rhat@localhost ~]$ pwd #执行pwd命令 ,因为重定向到out01.txt中,所以看不到输出. [rhat@localhost ~]$ echo "HelloWorld,I'm a sehll" #执行echo命令 [rhat@localhost ~]$ exec >/dev/tty #将标准输出重定向到显示器. [rhat@localhost ~]$ cat out01.txt #查看之前两个命令执行的结果. /home/rhat HelloWorld,I'm a sehll
3.指定文件标识符.
通过exec指定文件标识符,可以通过对该标识符操作进行文件的操作.拿排序为例.
[rhat@localhost ~]$ exec 3<fruit01.txt [rhat@localhost ~]$ cat fruit01.txt banana apple carrot [rhat@localhost ~]$ sort <&3 #在Linux中,文件标识符也是一种"设备",这个标识符会出现在/dev/fd目录中。进入这个目录,可以看到3是一个到该文件的软连接---:Linux下一切皆文件. apple banana carrot
4.关闭文件标识符.
主动打开的问价标识符需要主动关闭,否则除了系统系统重启,该文件标识符会一直被占用.
[rhat@localhost ~]$ exec 3<&- [rhat@localhost ~]$ ls -l /dev/fd lrwxrwxrwx. 1 root root 13 Sep 26 00:45 /dev/fd -> /proc/self/fd [rhat@localhost ~]$ ls -l /proc/self/fd total 0 lrwx------. 1 rhat rhat 64 Sep 28 03:45 0 -> /dev/pts/0 l-wx------. 1 rhat rhat 64 Sep 28 03:45 1 -> /dev/tty lrwx------. 1 rhat rhat 64 Sep 28 03:45 2 -> /dev/pts/0 lr-x------. 1 rhat rhat 64 Sep 28 03:45 3 -> /proc/60867/fd
5.将写入指定文件标识符的内容写入制定文件
#创建文件标识符3,并将写入3的内容全部写入file.txt文件中. [rhat@localhost ~]$ exec 3>file.txt #命令的输出内容写到标识符3中. [rhat@localhost ~]$ echo "Hello , world" >&3 [rhat@localhost ~]$ cat file.txt Hello , world
6.创建文件标识符的拷贝
[rhat@localhost ~]$ exec 3<fruit01.txt #创建文件标识符3的拷贝4 [rhat@localhost ~]$ exec 4<&3 #可以看到3和4都指向同一个文件 [rhat@localhost ~]$ ls -l /dev/fd/ total 0 lrwx------. 1 rhat rhat 64 Sep 28 03:54 0 -> /dev/pts/0 l-wx------. 1 rhat rhat 64 Sep 28 03:54 1 -> /dev/tty lrwx------. 1 rhat rhat 64 Sep 28 03:54 2 -> /dev/pts/0 lr-x------. 1 rhat rhat 64 Sep 28 03:54 3 -> /home/rhat/fruit01.txt lr-x------. 1 rhat rhat 64 Sep 28 03:54 4 -> /home/rhat/fruit01.txt lr-x------. 1 rhat rhat 64 Sep 28 03:54 5 -> /proc/61127/fd [rhat@localhost ~]$ cat /dev/fd/4 banana apple carrot
Here Document又称为此处文档,用于在命令或脚本中按行输入文本。Here Document的格式为<<delimiter,其中delimiter是一个用于标注"分割符",该分隔符后所有的输入都被当做是输入的文本,直到出现下一个分隔符为止.
在脚本中收输入如下:
[rhat@localhost ~]$ sort << END > a > b > c > END a b c #以文件为例: [rhat@localhost ~]$ cat >> HelloWord01.txt << END #>>为追加重定向符号,<<END 为标准输入重定向符号. > hello > world > ni > hao > END [rhat@localhost ~]$ cat HelloWord01.txt hello world ni hao