`

第十一章 数据流重导向

 
阅读更多
数据流重导向 (redirect) 由字面上的意思来看,好像就是将『数据给他传导到其他地方去』的样子? 没错~数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了!

什么是数据流重导向

什么是数据流重导向啊?这得要由命令的运行结果谈起!一般来说,如果你要运行一个命令,通常他会是这样的:



我们运行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。 在上图当中, standard output 与 standard error output 分别代表『标准输出』与『标准错误输出』, 这两个玩意儿默认都是输出到屏幕上面来的啊!那么什么是标准输出与标准错误输出呢?

standard output 与 standard error output

简单的说,标准输出指的是『命令运行所回传的正确的信息』,而标准错误输出可理解为『 命令运行失败后,所回传的错误信息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无 /etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个命令时,cat 会进行:

1.标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
2.标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误信息

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!那能不能透过某些机制将这两股数据分开呢? 当然可以啊!那就是数据流重导向的功能啊!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:

1.标准输入  (stdin) :代码为 0 ,使用 < 或 << ;
2.标准输出  (stdout):代码为 1 ,使用 > 或 >> ;
3.标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

为了理解 stdout 与 stderr ,我们先来进行一个范例的练习:

范例一:观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来
[root@www ~]# ll /  <==此时屏幕会显示出文件名信息

[root@www ~]# ll / > ~/rootfile <==屏幕并无任何信息
[root@www ~]# ll  ~/rootfile <==有个新档被创建了!
-rw-r--r-- 1 root root 1089 Feb  6 17:00 /root/rootfile


怪了!屏幕怎么会完全没有数据呢?这是因为原本『 ll / 』所显示的数据已经被重新导向到 ~/rootfile 文件中了! 那个 ~/rootfile 的档名可以随便你取。如果你下达『 cat ~/rootfile 』那就可以看到原本应该在屏幕上面的数据啰。 如果我再次下达:『 ll /home > ~/rootfile 』后,那个 ~/rootfile 文件的内容变成什么? 他将变成『仅有 ll /home 的数据』而已!咦!原本的『 ll / 』数据就不见了吗?是的!因为该文件的创建方式是:

该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他创建起来,但是
当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉啰!


那如果我想要将数据累加而不想要将旧的数据删除,那该如何是好?利用两个大于的符号 (>>) 就好啦!以上面的范例来说,你应该要改成『 ll / >> ~/rootfile 』即可。 如此一来,当 (1) ~/rootfile 不存在时系统会主动创建这个文件;(2)若该文件已存在, 则数据会在该文件的最下方累加进去!

上面谈到的是 standard output 的正确数据,那如果是 standard error output 的错误数据呢?那就透过 2> 及 2>> 啰!同样是覆盖 (2>) 与累加 (2>>) 的特性!我们在刚刚才谈到 stdout 代码是 1 而 stderr 代码是 2 , 所以这个 2> 是很容易理解的,而如果仅存在 > 时,则代表默认的代码 1 啰!也就是说:

1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;


要注意喔,『 1>> 』以及『 2>> 』中间是没有空格的!OK!有些概念之后让我们继续聊一聊这家伙怎么应用吧! 当你以一般身份运行 find 这个命令的时候,由于权限的问题可能会产生一些错误信息。例如运行『 find / -name testing 』时,可能会产生类似『 find: /root: Permission denied 』之类的信息。 例如底下这个范例:

范例二:利用一般身份账号搜寻 /home 底下是否有名为 .bashrc 的文件存在
[root@www ~]# su - dmtsai  <==假设我的系统有名为 dmtsai 的账号
[dmtsai@www ~]$ find /home -name .bashrc <==身份是 dmtsai 喔!
find: /home/lost+found: Permission denied  <== Standard error
find: /home/alex: Permission denied        <== Standard error
find: /home/arod: Permission denied        <== Standard error
/home/dmtsai/.bashrc                       <== Standard output


由于 /home 底下还有我们之前创建的账号存在,那些账号的家目录你当然不能进入啊!所以就会有错误及正确数据了。 好了,那么假如我想要将数据输出到 list 这个文件中呢?运行『 find /home -name .bashrc > list 』 会有什么结果?呵呵,你会发现 list 里面存了刚刚那个『正确』的输出数据, 至于屏幕上还是会有错误的信息出现呢!伤脑筋!如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?

范例三:承范例二,将 stdout 与 stderr 分存到不同的文件去
[dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error


注意喔,此时『屏幕上不会出现任何信息』!因为刚刚运行的结果中,有 Permission 的那几行错误信息都会跑到 list_error 这个文件中,至于正确的输出数据则会存到 list_right 这个文件中啰!这样可以了解了吗? 如果有点混乱的话,去休息一下再来看看吧!

/dev/null 垃圾桶黑洞装置与特殊写法

想象一下,如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或储存呢? 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!将上述的范例修订一下:

范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据
[dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc  <==只有 stdout 会显示到屏幕上, stderr 被丢弃了


再想象一下,如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 我们同样用底下的案例来说明:

范例五:将命令的数据全部写入名为 list 的文件中
[dmtsai@www ~]$ find /home -name .bashrc > list 2> list  <==错误
[dmtsai@www ~]$ find /home -name .bashrc > list 2>&1     <==正确
[dmtsai@www ~]$ find /home -name .bashrc &> list         <==正确


上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。 至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &> ! 一般来说,鸟哥比较习惯使用 2>&1 的语法啦!

standard input : < 与 <<

了解了 stderr 与 stdout 后,那么那个 < 又是什么呀?呵呵!以最简单的说法来说, 那就是『将原本需要由键盘输入的数据,改由文件内容来取代』的意思。 我们先由底下的 cat 命令操作来了解一下什么叫做『键盘输入』吧!

范例六:利用 cat 命令来创建一个文件的简单流程
[root@www ~]# cat > catfile
testing
cat file test
<==这里按下 [ctrl]+d 来离开

[root@www ~]# cat catfile
testing
cat file test


由于加入 > 在 cat 后,所以那个 catfile 会被主动的创建,而内容就是刚刚键盘上面输入的那两行数据了。 唔!那我能不能用纯文本文件取代键盘的输入,也就是说,用某个文件的内容来取代键盘的敲击呢? 可以的!如下所示:

范例七:用 stdin 取代键盘的输入以创建新文件的简单流程
[root@www ~]# cat > catfile < ~/.bashrc
[root@www ~]# ll catfile ~/.bashrc
-rw-r--r-- 1 root root 194 Sep 26 13:36 /root/.bashrc
-rw-r--r-- 1 root root 194 Feb  6 18:29 catfile
# 注意看,这两个文件的大小会一模一样!几乎像是使用 cp 来复制一般!


这东西非常的有帮助!尤其是用在类似 mail 这种命令的使用上。 理解 < 之后,再来则是怪可怕一把的 << 这个连续两个小于的符号了。 他代表的是『结束的输入字符』的意思!举例来讲:『我要用 cat 直接将输入的信息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束』,那我可以这样做:

[root@www ~]# cat > catfile << "eof"
> This is a test.
> OK now stop
> eof  <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d

[root@www ~]# cat catfile
This is a test.
OK now stop     <==只有这两行,不会存在关键词那一行!



看到了吗?利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!这对程序写作很有帮助喔!好了,那么为何要使用命令输出重导向呢?我们来说一说吧!

1.屏幕输出的信息很重要,而且我们需要将他存下来的时候;
2.背景运行中的程序,不希望他干扰屏幕正常的输出结果时;
3.一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的运行结果,希望他可以存下来时;
4.一些运行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;
5.错误信息与正确信息需要分别输出时。

当然还有很多的功能的,最简单的就是网友们常常问到的:『为何我的 root 都会收到系统 crontab 寄来的错误信息呢』这个咚咚是常见的错误, 而如果我们已经知道这个错误信息是可以忽略的时候,嗯!『 2> errorfile 』这个功能就很重要了吧! 了解了吗?

命令运行的判断依据: ; , &&, ||

在某些情况下,很多命令我想要一次输入去运行,而不想要分次运行时,该如何是好?基本上你有两个选择, 一个是透过第十三章要介绍的 shell script 撰写脚本去运行,一种则是透过底下的介绍来一次输入多重命令喔!

cmd ; cmd (不考虑命令相关性的连续命令下达)

在某些时候,我们希望可以一次运行多个命令,例如在关机的时候我希望可以先运行两次 sync 同步化写入磁盘后才 shutdown 计算机,那么可以怎么作呢?这样做呀:

[root@www ~]# sync; sync; shutdown -h now


在命令与命令中间利用分号 (;) 来隔开,这样一来,分号前的命令运行完后就会立刻接着运行后面的命令了。 这真是方便啊~再来,换个角度来想,万一我想要在某个目录底下创建一个文件,也就是说,如果该目录存在的话, 那我才创建这个文件,如果不存在,那就算了。也就是说这两个命令彼此之间是有相关性的, 前一个命令是否成功的运行与后一个命令是否要运行有关!那就得动用到 && 或 || 啰!

$? (命令回传值) 与 && 或 ||

如同上面谈到的,两个命令之间有相依性,而这个相依性主要判断的地方就在于前一个命令运行的结果是否正确。 还记得本章之前我们曾介绍过命令回传值吧!嘿嘿!没错,您真聪明!就是透过这个回传值啦! 再复习一次『若前一个命令运行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值』。 那么我们怎么透过这个回传值来判断后续的命令是否要运行呢?这就得要藉由『 && 』及『 || 』的帮忙了! 注意喔,两个 & 之间是没有空格的!那个 | 则是 [Shift]+[\] 的按键结果。

命令下达情况 说明
cmd1 && cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则开始运行 cmd2。
                2. 若 cmd1 运行完毕且为错误 ($?≠0),则 cmd2 不运行。
cmd1 || cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则 cmd2 不运行。
                2. 若 cmd1 运行完毕且为错误 ($?≠0),则开始运行 cmd2。

上述的 cmd1 及 cmd2 都是命令。好了,回到我们刚刚假想的情况,就是想要: (1)先判断一个目录是否存在; (2)若存在才在该目录底下创建一个文件。由于我们尚未介绍如何判断式 (test) 的使用,在这里我们使用 ls 以及回传值来判断目录是否存在啦! 让我们进行底下这个练习看看:

范例一:使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 创建 /tmp/abc/hehe 
[root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
ls: /tmp/abc: No such file or directory 
# ls 很干脆的说明找不到该目录,但并没有 touch 的错误,表示 touch 并没有运行

[root@www ~]# mkdir /tmp/abc
[root@www ~]# ls /tmp/abc && touch /tmp/abc/hehe
[root@www ~]# ll /tmp/abc
-rw-r--r-- 1 root root 0 Feb  7 12:43 hehe


看到了吧?如果 /tmp/abc 不存在时,touch 就不会被运行,若 /tmp/abc 存在的话,那么 touch 就会开始运行啰! 很不错用吧!不过,我们还得手动自行创建目录,伤脑筋~能不能自动判断,如果没有该目录就给予创建呢? 参考一下底下的例子先:

范例二:测试 /tmp/abc 是否存在,若不存在则予以创建,若存在就不作任何事情
[root@www ~]# rm -r /tmp/abc                <==先删除此目录以方便测试
[root@www ~]# ls /tmp/abc || mkdir /tmp/abc
ls: /tmp/abc: No such file or directory <==真的不存在喔!
[root@www ~]# ll /tmp/abc                  
total 0                                 <==结果出现了!有进行 mkdir


如果你一再重复『 ls /tmp/abc || mkdir /tmp/abc 』画面也不会出现重复 mkdir 的错误!这是因为 /tmp/abc 已经存在, 所以后续的 mkdir 就不会进行!这样理解否?好了,让我们再次的讨论一下,如果我想要创建 /tmp/abc/hehe 这个文件, 但我并不知道 /tmp/abc 是否存在,那该如何是好?试看看:

范例三:我不清楚 /tmp/abc 是否存在,但就是要创建 /tmp/abc/hehe 文件
[root@www ~]# ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe




转自:http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_5.php
  • 大小: 10.9 KB
  • 大小: 4.9 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    《VBVisualBasic程序设计》课件PPT第11章文

    【描述】提到的"《VBVisualBasic程序设计》课件PPT第11章文件共10页.pdf.zip"是一个压缩文件,其中包含了一份10页的PPT课件,用于教授VB的第11章内容。PDF格式通常用于文档分享和阅读,保证了内容的原貌不受损失。而...

    数据结构与算法:C#_语言描述(中文)

    第十一章至第十五章依次探讨了链表、二叉树、二叉查找树以及其他高级数据结构,如AVL树、红黑树和跳跃表,每种数据结构都有其独特的应用场景和优势。 第十六章讨论了图及其算法,特别是在网络表示方面的应用,而第...

    第11章虚拟局域网.pptx

    3. **按第三层协议**(IP地址或协议类型):常用且灵活,便于服务导向的配置,但可能增加网络处理开销。 4. **IP多播组**:利用D类IP地址,站点只需响应多播即可加入VLAN,适用于多媒体流等场景。 5. **其他方式...

    流行病学人卫第六版课件第11章疾病预防策略与措施.pptx

    第六版流行病学教材深入探讨了疾病预防策略与措施,旨在揭示疾病发生的规律,指导公共卫生实践。本章重点关注疾病预防的策略制定、实施依据、我国的预防工作总策略以及面临的公共卫生形势。\n\n1. **策略制定的必要...

    第五章审计技术与方法.pptx

    本章主要探讨了审计导向模式的历史演变,从账项导向审计到系统导向和风险导向审计模式的转变,以及这些变化如何适应内部控制体系的完善和成本效益的追求。 **账项导向审计模式** 账项导向审计模式主要流行于20世纪...

    马丙鹏_计算机算法设计与分析_第四章_11

    第四章主要探讨的是贪心方法在计算机算法设计与分析中的应用。贪心方法是一种解决问题的策略,它通过每一步选择局部最优解来逐步构建全局最优解。这种方法在很多实际问题中展现出高效性,例如资源分配、任务调度和...

    注册会计师(财务管理)第二十章业绩评价.docx

    【注册会计师(财务管理)第二十章 业绩评价】 业绩评价是财务管理中不可或缺的一部分,它帮助企业评估其运营效率和效果,以便做出改进决策。本章主要探讨财务业绩评价和非财务业绩评价的区别及其应用。 1. **财务...

    Beginning.Microsoft.Visual.C.Sharp.pdf

    第十一章介绍了集合类型(如List、Dictionary)的使用,以及元素的比较和类型转换规则。 #### 12. 泛型 第十二章讲解了泛型的概念和使用,通过泛型可以创建可重用的、类型安全的代码组件。 #### 13. 更多OOP技巧 ...

    第11章客户关系管理与企业变革客户关系管理.pptx

    2. **CRM如何提升核心竞争力**:CRM充实企业资源,例如通过数据驱动的决策支持提升商业决策能力,通过信息共享提高管理效率。同时,CRM系统可以促进知识管理,积累和传播企业的知识资产,帮助企业保持竞争优势。 3....

    Marco Cantu - Mastering Delphi 7

    #### 第十一章:建模与面向对象编程(使用ModelMaker) ModelMaker是Delphi提供的一个UML建模工具,本章介绍了如何使用ModelMaker进行软件设计和代码生成,以提升编程效率和代码质量。 #### 第十二章:从COM到COM+...

    Java编程思想(第四版)1

    第十一章“运行期类型识别”讲解了运行期类型信息(RTTI)和反射,这是动态获取类信息和操作的关键技术。 第十二章“传递和返回对象”讨论了对象的传递方式,包括引用传递、克隆、只读类的设计等,这些都是处理对象...

    第十四章 电子商务与物流.pptx

    物流系统在电子商务中扮演着关键角色,它是一个开放、信息化、以信息流为导向,并具有规模优势的有机整体。电子商务对物流系统提出了新要求,如信息化、网络化运作,标准化、信息化的运作水平,快速反应能力,动态...

    ERP课件 第11章 供应链管理与客户关系管理.ppt.ppt

    4. **消费者导向**:面对消费者行为的变化,如个性化需求、对性价比和服务质量的关注,企业必须以消费者为中心,通过CRM系统收集并分析消费者数据,以便制定更精准的营销策略和提供定制化服务。 综上所述,ERP中的...

    WF从入门到精通(1-16章)

    #### 第十一章:并行活动 - **并行执行的概念**:解释并行执行的基本原理,即如何在同一时刻执行多个活动或工作流。 - **并行分支活动**:介绍并行分支活动的使用方法,包括如何创建并行分支、如何指定分支间的依赖...

    Professional Visual Studio 2012.pdf

    - 第11章:单元测试 - 第12章:使用XML注释进行文档化 - 第13章:代码一致性工具 - 第14章:使用T4进行代码生成 - 第15章:项目和项目项模板 - 第16章:语言特定功能 #### 第四部分:富客户端应用程序 (Rich Client...

    C# sharp 入门经典全英文版第五版 2010 Beginning Visual C#

    - **第11章:集合、比较和转换** - 介绍了集合框架中的基本数据结构,如List、Dictionary等。 - 探讨了集合的操作方法、排序和搜索算法。 - **第12章:泛型** - 介绍了泛型的概念及其在集合和方法中的应用。 - ...

    java语言程序设计基础篇第十版第十三章练习答案.docx

    在给定的文件中,我们看到了三个Java编程练习的解答,涵盖了对象导向编程、集合以及算法的基本概念。下面是这些知识点的详细说明: 1. **面向对象编程**: - `Exercise13_01` 类定义了一个名为 `TriangleNew` 的类...

Global site tag (gtag.js) - Google Analytics