Shell学习-13-Shell重定向

在人生的道路上,不管是潇洒走一回,或者是千山独行,皆须是自己想走的路,虽然,有的人并不是很快就能找到自己的方向和道路,不过,只要坚持到底,我相信,就一定可以找到自己的路,只要找到路,就不必怕路途遥远了。

导读:本篇文章讲解 Shell学习-13-Shell重定向,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

3.1 Shell重定向

  • Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向;从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思。

  • 一般情况下,我们都是从键盘读取用户输入的数据,然后再把数据拿到程序(C语言程序、Shell 脚本程序等)中使用;这就是标准的输入方向,也就是从键盘到程序。反过来说,程序中也会产生数据,这些数据一般都是直接呈现到显示器上,这就是标准的输出方向,也就是从程序到显示器。

  • 输入输出方向就是数据的流动方向:

    • 输入方向就是数据从哪里流向程序。数据默认从键盘流向程序,如果改变了它的方向,数据就从其它地方流入,这就是输入重定向。
    • 输出方向就是数据从程序流向哪里。数据默认从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向。
3.2 硬件设备和文件描述符
  • 计算机的硬件设备有很多,常见的输入设备有键盘、鼠标等,输出设备有显示器、投影仪、打印机等。不过,在 Linux 中,标准输入设备指的是键盘,标准输出设备指的是显示器。
  • Linux 中一切皆文件,包括标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件。为了表示和区分已经打开的文件,Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。
文件描述符 文件名 类型 硬件
0 stdin 标准输入文件 键盘
1 stdout 标准输出文件 显示器
2 stderr 标准错误输出文件 显示器
  • Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。stdin、stdout、stderr 默认都是打开的,在重定向的过程中,0、1、2 这三个文件描述符可以直接使用。
3.3 Linux Shell 输出重定向
  • 输出重定向是指命令的结果不再输出到显示器上,而是输出到其它地方,一般是文件中。这样做的最大好处就是把命令的结果保存起来,当我们需要的时候可以随时查询。Bash 支持的输出重定向符号如下表所示。
类 型 符 号 作 用
标准输出重定向 command >file 以覆盖的方式,把 command 的正确输出结果输出到 file 文件中。
command >>file 以追加的方式,把 command 的正确输出结果输出到 file 文件中。
标准错误输出重定向 command 2>file 以覆盖的方式,把 command 的错误信息输出到 file 文件中。
command 2>>file 以追加的方式,把 command 的错误信息输出到 file 文件中。
正确输出和错误信息同时保存 command >file 2>&1 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command >>file 2>&1 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。
command >file1 2>file2 以覆盖的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。
command >>file1 2>>file2 以追加的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。
command >file 2>file 不推荐】这两种写法会导致 file 被打开两次,引起资源竞争,所以 stdout 和 stderr 会互相覆盖.
command >>file 2>>file 同上

注意:

  • 输出重定向的完整写法其实是fd>file或者fd>>file,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。

  • 当文件描述符为 1 时,一般都省略不写,如上表所示;当然,如果你愿意,也可以将command >file写作command 1>file,但这样做是多此一举。

  • 当文件描述符为大于 1 的值时,比如 2,就必须写上。

  • 重点说明的是,fd和>之间不能有空格,否则 Shell 会解析失败;>和file之间的空格可有可无。为了保持一致,我习惯在>两边都不加空格。

  • 反例:
echo "www.baidu.com" 1 >log.txt

注意1>之间的空格。echo 命令的输出结果是www.baidu.com,将输出结果重定向到 log.txt,但是当你打开 log.txt 文件后,发现文件的内容为www.baidu.com 1,这就是多余的空格导致的解析错误。也就是说,Shell 将该条语句理解成了下面的形式:

echo "www.baidu.com" 1 1>log.txt
  • 输出重定向举例:将 echo 命令的输出结果以追加的方式写入到 log.txt 文件中。
[root@localhost testshell]# touch test1.sh && vi test1.sh
#!/bin/bash
for str in "百度" "www.baidu.com" "搜索"		
do
echo $str >>log.txt							#将输入结果以追加的方式重定向到文件
done
~    
#运行以上脚本结果:
[root@localhost testshell]# . test1.sh
[root@localhost testshell]# cat log.txt
百度
www.baidu.com
搜索
  • ls -l命令的输出结果重定向到文件中。
#先预览一下输出结果
[root@localhost testshell]# ls -l
总用量 28
-rw-r--r-- 1 root root  64 11月 30 00:05 func1.sh
-rw-r--r-- 1 root root 112 11月 30 00:10 func2.sh
-rw-r--r-- 1 root root 139 11月 30 00:19 func3.sh
-rw-r--r-- 1 root root 196 11月 30 00:23 func4.sh
-rw-r--r-- 1 root root  28 11月 30 11:54 log.txt
-rw-r--r-- 1 root root  85 11月 30 11:54 test1.sh
-rw-r--r-- 1 root root   1 11月 29 11:49 urls.txt
#重定向
[root@localhost testshell]# ls -l >log.txt
 #查看文件内容
[root@localhost testshell]# cat log.txt
总用量 24
-rw-r--r-- 1 root root  64 11月 30 00:05 func1.sh
-rw-r--r-- 1 root root 112 11月 30 00:10 func2.sh
-rw-r--r-- 1 root root 139 11月 30 00:19 func3.sh
-rw-r--r-- 1 root root 196 11月 30 00:23 func4.sh
-rw-r--r-- 1 root root   0 11月 30 11:56 log.txt
-rw-r--r-- 1 root root  85 11月 30 11:54 test1.sh
-rw-r--r-- 1 root root   1 11月 29 11:49 urls.txt

  • 错误输出重定向:命令正确执行是没有错误信息的,我们必须刻意地让命令执行出错,如下所示:
#先预览一下错误信息
[root@localhost testshell]# ls demo 
ls: 无法访问demo: 没有那个文件或目录
#重定向
[root@localhost testshell]# ls demo 2>err.log
#查看文件
[root@localhost testshell]# cat err.log
ls: 无法访问demo: 没有那个文件或目录
  • 正确输出和错误信息同时保存:把正确结果和错误信息都保存到一个文件中,例如:
[root@localhost testshell]# ls -l >log.txt 2>&1
[root@localhost testshell]# ls demo >>log.txt 2>&1
[root@localhost testshell]# cat log.txt
总用量 28
-rw-r--r-- 1 root root  50 11月 30 11:59 err.log
-rw-r--r-- 1 root root  64 11月 30 00:05 func1.sh
-rw-r--r-- 1 root root 112 11月 30 00:10 func2.sh
-rw-r--r-- 1 root root 139 11月 30 00:19 func3.sh
-rw-r--r-- 1 root root 196 11月 30 00:23 func4.sh
-rw-r--r-- 1 root root   0 11月 30 12:03 log.txt
-rw-r--r-- 1 root root  85 11月 30 11:54 test1.sh
-rw-r--r-- 1 root root   1 11月 29 11:49 urls.txt
ls: 无法访问demo: 没有那个文件或目录
#log.txt的最后一行是错误信息,其它行都是正确的输出结果。
  • 上面的实例将正确结果和错误信息都写入同一个文件中,这样会导致视觉上的混乱,不利于以后的检索,所以我建议把正确结果和错误信息分开保存到不同的文件中,也即写成下面的形式:
#正确的输出结果会写入到 out.log,而错误的信息则会写入到 err.log。
[root@localhost testshell]# ls -l >>out.log 2>>err.log
  • /dev/null 文件:如果你既不想把命令的输出结果保存到文件,也不想把命令的输出结果显示到屏幕上,干扰命令的执行,那么可以把命令的所有结果重定向到 /dev/null 文件中。如下所示:
ls -l &>/dev/null

可以把 /dev/null 当成 Linux 系统的垃圾箱,任何放入垃圾箱的数据都会被丢弃,不能恢复.

3.4 Linux Shell 输入重定向
  • 输入重定向就是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件作为命令的输入。
符号 说明
command <file 将 file 文件中的内容作为 command 的输入。
command <<END 从标准输入(键盘)中读取数据,直到遇见分界符 END 才停止(分界符可以是任意的字符串,用户自己定义)。
command file2 将 file1 作为 command 的输入,并将 command 的处理结果输出到 file2。

和输出重定向类似,输入重定向的完整写法是fd<file,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。

  • **输入重定向举例:**统计文档中有多少行文字。

  • wc 命令可以用来对文本进行统计,包括单词个数、行数、字节数,它的用法如下:

wc  [选项]  [文件名]
#其中,-c选项统计字节数,-w选项统计单词数,-l选项统计行数。
  • 统计 out.txt 文件中有多少行文本:
[root@localhost testshell]# cat out.log
总用量 20
-rw-r--r-- 1 root root   0 11月 30 12:07 err.log
-rw-r--r-- 1 root root  64 11月 30 00:05 func1.sh
-rw-r--r-- 1 root root 112 11月 30 00:10 func2.sh
-rw-r--r-- 1 root root 139 11月 30 00:19 func3.sh
-rw-r--r-- 1 root root 196 11月 30 00:23 func4.sh
-rw-r--r-- 1 root root   0 11月 30 12:07 out.log
-rw-r--r-- 1 root root  85 11月 30 11:54 test1.sh
[root@localhost testshell]# wc -l <out.log
8

  • 逐行读取文件内容。
[root@localhost testshell]# touch test2.sh && vi test2.sh
#!/bin/bash
while read str 
do
echo $str
done <out.log
#运行结果
[root@localhost testshell]# . test2.sh
总用量 20
-rw-r--r-- 1 root root 0 11月 30 12:07 err.log
-rw-r--r-- 1 root root 64 11月 30 00:05 func1.sh
-rw-r--r-- 1 root root 112 11月 30 00:10 func2.sh
-rw-r--r-- 1 root root 139 11月 30 00:19 func3.sh
-rw-r--r-- 1 root root 196 11月 30 00:23 func4.sh
-rw-r--r-- 1 root root 0 11月 30 12:07 out.log
-rw-r--r-- 1 root root 85 11月 30 11:54 test1.sh

这种写法叫做代码块重定向,也就是把一组命令同时重定向到一个文件

  • 统计用户在终端输入的文本的行数:使用输入重定向符号<<,这个符号的作用是使用特定的分界符作为命令输入的结束标志,而不使用 Ctrl+D 键。
[root@localhost testshell]# wc -l <<end
> www
> baidu
> com
> end
3

wc 命令会一直等待用输入,直到遇见分界符 END 才结束读取。

<<之后的分界符可以自由定义,只要再碰到相同的分界符,两个分界符之间的内容将作为命令的输入(不包括分界符本身)。

参考文献:
Linux Shell重定向(输入输出重定向)精讲

下一篇:Shell学习-14-linux管道

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123680.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!