shell十三问之11:>与< 差在哪?

发表于 4年以前  | 总阅读数:1502 次

shell十三问之11:>与< 差在哪?

这次的题目,之前我在CU的shell版说明过了: (原帖的连接在论坛改版后,已经失效) 这次我就不重写了,将帖子的内容“抄”下来就是了...

1. 文件描述符(fd, File Descriptor)


谈到I/O redirection,不妨先让我们认识一下File Descriptor(fd,文件描述符)。

进程的运算,在大部分情况下,都是进行数据(data)的处理, 这些数据从哪里,读进来?又输出到哪里呢? 这就是file descriptor(fd)的功用了。

在shell的进程中,最常使用的fd大概有三个,分别为:

  • 0:standard Input (STDIN)
  • 1: standard output(STDOUT)
  • 2: standard Error output (STDERR

在标准情况下,这些fd分别跟如下设备(device)关联:

  • stdin(0): keyboard
  • stdout(1): monitor
  • stderr(2): monitor

Tips: linux中的文件描述符(fd)用整数表示。 linux中任何一个进程都默认打开三个文件, 这三个文件对应的文件描述符分别是:0, 1, 2; 即stdin, stdout, stderr.

我们可以用如下命令测试一下:

$ mail -s test root
this is a test mail。
please skip.
^d (同时按下ctrl 跟d键)

很明显,mail进程所读进的数据,就是从 stdin 也就是keyboard读进的。 不过,不见得每个进程的stdin都跟mail一样 从keyboard读进,因为进程的作者可以从文件参数读进stdin, 如:

$ cat /etc/passwd

但,要是cat之后没有文件参数则如何呢? 哦, 请你自己玩玩看...^_^

$ cat

Tips:

请留意数据输出到哪里去了, 最后别忘了按ctrl+d(^d), 退出stdin输入。

至于stdoutstderr,嗯...等我有空再续吧...^_^ 还是,有哪位前辈来玩接龙呢?

相信,经过上一个练习后, 你对stdinstdout应该不难理解了吧? 然后,让我们看看stderr好了。

事实上,stderr没什么难理解的: 说白了就是“错误信息”要往哪里输出而已... 比方说, 若读进的文件参数不存在的, 那我们在monitor上就看到了:

$ ls no.such.file
ls: no.such.file: No such file or directory

若同一个命令,同时成生stdoutstderr呢? 那还不简单,都送到monitor来就好了:

$ touch my.file
$ ls my.file on.such.file
ls: no.such.file: No such file or directory
my.file

okay, 至此,关于fd及其名称、还有相关联的设备, 相信你已经没问题了吧?


2. I/O 重定向(I/O Redirection)


那好,接下来让我们看看如何改变这些fd的预设数据通道。

  • < 来改变读进的数据通道(stdin),使之从指定的文件读进。
  • > 来改变输出的数据通道(stdout,stderr),使之输出到指定的文件。

2.1 输入重定向n<(input redirection)

比方说:

$ cat < my.file

就是从my.file读入数据

$ mail -s test root < /etc/passwd

则是从/etc/passwd读入...

这样一来,stdin将不再是从keyboard读入, 而是从指定的文件读入了...

严格来说,**<符号之前需要指定一个fd的(之前不能有空白),但因为0是<的预设值,因此,<0<是一样的***。

okay,这样好理解了吧?

那要是用两个<,即<<又是啥呢? 这是所谓的here document, 它可以让我们输入一段文本, 直到读到<< 后指定的字符串

比方说:

$ cat <<EOF
first line here
second line here
third line here
EOF

这样的话, cat会读入3个句子, 而无需从keyboard读进数据且要等到(ctrl+d, ^d)结束输入。


2.2 重定向输出>n(output redirection)

当你搞懂了0< 原来就是改变stdin的数据输入通道之后, 相信要理解如下两个redirection就不难了:

  • 1> #改变stdout的输出通道;
  • 2> #改变stderr的输出通道;

两者都是将原来输出到monitor的数据, 重定向输出到指定的文件了。

由于1是>的预设值, 因此,1>>是相同的,都是改变stdout.

用上次的ls的例子说明一下好了:

$ ls my.file no.such.file 1>file.out
ls: no.such.file: No such file or directory

这样monitor的输出就只剩下stderr的输出了, 因为stdout重定向输出到文件file.out去了。

$ ls my.file no.such.file 2>file.err
my.file

这样monitor就只剩下了stdout, 因为stderr重定向输出到文件file.err了。

$ ls my.file no.such.file 1>file.out 2>file.err

这样monitor就啥也没有了, 因为stdoutstderr都重定向输出到文件了。

呵呵,看来要理解>一点也不难啦是不? 没骗你吧? ^_^ 不过有些地方还是要注意一下的

$ ls my.file no.such.file 1>file.both 2>file.both

假如stdout(1)与stderr(2)都同时在写入file.both的话, 则是采取"覆盖"的方式:后来写入覆盖前面的。

让我们假设一个stdoutstderr同时写入到file.out的情形好了;

  • 首先stdout写入10个字符
  • 然后stderr写入6个字符

那么,这时原本的stdout输出的10个字符, 将被stderr输出的6个字符覆盖掉了。

那如何解决呢?所谓山不转路转,路不转人转嘛, 我们可以换一个思维: 将stderr导进stdout 或者将stdout导进到stderr, 而不是大家在抢同一份文件,不就行了。 bingo就是这样啦:

  • 2>&1 #将stderr并进stdout输出
  • 1>&2 或者 >&2 #将stdout并进stderr输出。

于是,前面的错误操作可以改写为:

$ ls my.file no.such.file 1>file.both 2>&1
$ ls my.file no.such.file 2>file.both >&2

这样,不就皆大欢喜了吗? ~~~ ^_^

不过,光解决了同时写入的问题还不够, 我们还有其他技巧需要了解的。 故事还没有结束,别走开广告后,我们在回来....


2.3 I/O重定向与linux中的/dev/null

okay,这次不讲I/O Redirection, 请佛吧... (有没有搞错?网中人是否头壳烧坏了?...)嘻~~~^_^

学佛的最高境界,就是"四大皆空"。 至于是空哪四大块,我也不知,因为我还没有到那个境界.. 这个“空”字,却非常值得反复把玩: ---色即是空,空即是色 好了,施主要是能够领会"空"的禅意,那离修成正果不远了。

在linux的文件系统中,有个设备文件: /dev/null. 许多人都问过我,那是什么玩意儿? 我跟你说好了,那就是"空"啦。

没错空空如也的空就是null了... 请问施主是否忽然有所顿悟了呢? 然则恭喜了。

这个null在 I/O Redirection中可有用的很呢?

  • 将fd 1跟fd 2重定向到/dev/null去,就可忽略stdout, stderr的输出。
  • 将fd 0重定向到/dev/null,那就是读进空(nothing).

比方说,我们在执行一个进程时,会同时输出到stdout与stderr, 假如你不想看到stderr(也不想存到文件), 那就可以:

$ ls my.file no.such.file 2>/dev/null
my.file

若要相反:只想看到stderr呢? 还不简单将stdout,重定向的/dev/null就行:

$ ls my.file no.such.file >/dev/null
ls: no.such.file: No such file or directory

那接下来,假如单纯的只跑进程,而不想看到任何输出呢? 哦,这里留了一手,上次没讲的法子,专门赠与有缘人... ^_^ 除了用 >/dev/null 2>&1之外,你还可以如此:

$ ls my.file no.such.file &>/dev/null

Tips:

将&>换成>&也行!


2.4 重定向输出append (>>)

okay? 请完佛,接下来,再让我们看看如下情况:

$ echo "1" > file.out
$ cat file.out
1
$ echo "2" > file.out
$ cat file.out
2

看来,我们在重定向stdout或stderr进一个文件时, 似乎永远只能获得最后一次的重定向的结果. 那之前的内容呢?

呵呵,要解决这个问题,很简单啦,将>换成>> 就好了;

$ echo "3" >> file.out
$ cat file.out
2
3

如此一来,被重定向的文件的之前的内容并不会丢失, 而新的内容则一直追加在最后面去。so easy?...

但是,只要你再次使用>来重定向输出的话, 那么,原来文件的内容被truncated(清洗掉)。 这是,你要如何避免呢? ----备份, yes,我听到了,不过,还有更好的吗? 既然与施主这么有缘分,老衲就送你一个锦囊妙法吧:

$ set -o noclobber
$ echo "4" > file.out
-bash:file: cannot overwrite existing file.

那,要如何取消这个限制呢? 哦,将set -o换成 set +o就行了:

$ set +o noclobber
$ echo "5" > file.out
$ cat file.out
5

再问:那有办法不取消而又“临时”改写目标文件吗? 哦,佛曰:不可告也。 啊,~开玩笑的,开玩笑啦~^_^, 哎,早就料到人心是不足的了

$ set -o noclobber
$ echo "6" >| file.out
$ cat file.out
6

留意到没有: >后面加个|就好, 注意: >|之间不能有空白哦...


2.5 I/O Redirection的优先级

呼....(深呼吸吐纳一下吧)~~~ ^_^ 再来还有一个难题要你去参透呢:

$ echo "some text here" >file
$ cat < file
some text here
$cat < file >file.bak
$cat < file.bak
some text here
$cat < file >file

嗯?注意到没有? ---怎么最后那个cat命令看到file是空的呢? why? why? why?

前面提到:$cat < file > file之后, 原本有内容的文件,结果却被清空了。 要理解这个现象其实不难, 这只是priority的问题而已: 在IO Redirection中, stdout与stderr的管道先准备好, 才会从stdin读入数据。 也就是说,在上例中,>file会将file清空, 然后才读入 < file。 但这时候文件的内容已被清空了,因此就变成了读不进任何数据。

哦,~原来如此~^_^ 那...如下两例又如何呢?

$ cat <> file
$ cat < file >>file

嗯...同学们,这两个答案就当练习题喽, 下课前交作业。

Tips: 我们了解到>file能够快速把文件file清空; 或者使用:>file同样可以清空文件, :>file>file的功能: 若文件file存在,则将file清空; 否则,创建空文件file (等效于touch file); 二者的差别在于>file的方式不一定在所有的shell的都可用。

exec 5<>file; echo "abcd" >&5; cat <&5 将file文件的输入、输出定向到文件描述符5, 从而描述符5可以接管file的输入输出; 因此,cat <>file等价于cat < file

cat < file >>file则使file内容成几何级数增长。

好了, I/O Redirection也快讲完了, sorry,因为我也只知道这么多而已啦~嘻~^_^ 不过,还有一样东东是一定要讲的,各位观众(请自行配乐~!#@$%): 就是pipe line也。


2.6 管道(pipe line)

谈到pipe line,我相信不少人都不会陌生: 我们在很多command line上常看到|符号就是pipe line了。

不过,pipe line究竟是什么东东呢? 别急别急...先查一下英文字典,看看pipe是什么意思? 没错他就是“水管”的意思... 那么,你能想象一下水管是怎样一个根接一根的吗? 又, 每根水管之间的input跟output又如何呢? 灵光一闪:原来pipe line的I/O跟水管的I/O是一模一样的: 上一个命令的stdout接到下一个命令的stdin去了 的确如此。不管在command line上使用了多少个pipe line, 前后两个command的I/O是彼此连接的 (恭喜:你终于开放了 ^_^ )

不过...然而...但是... ...stderr呢? 好问题不过也容易理解: 若水管漏水怎么办? 也就是说:在pipe line之间, 前一个命令的stderr是不会接进下一个命令的stdin的, 其输出,若不用2>file的话,其输出在monitor上来。 这点请你在pipe line运用上务必要注意的。

那,或许你有会问: 有办法将stderr也喂进下一个命令的stdin吗? (贪得无厌的家伙),方法当然是有的,而且,你早已学习过了。 提示一下就好:**请问你如何将stderr合并进stdout一同输出呢? 若你答不出来,下课后再来问我...(如果你脸皮足够厚的话...)

或许,你仍意犹未尽,或许,你曾经碰到过下面的问题: 在cmd1 | cmd2 | cmd3 | ... 这段pipe line中如何将cmd2的输出保存到一个文件呢?

若你写成cmd1 | cmd2 >file | cmd3的话, 那你肯定会发现cmd3的stdin是空的,(当然了,你都将 水管接到别的水池了) 聪明的你或许会如此解决:

cmd1 | cmd2 >file; cmd3 < file

是的,你可以这样做,但最大的坏处是: file I/O会变双倍,在command执行的整个过程中, file I/O是最常见的最大效能杀手。 凡是有经验的shell操作者,都会尽量避免或降低file I/O的频度。

那上面问题还有更好的方法吗? 有的,那就是tee命令了。 所谓的tee命令是在不影响原本I/O的情况下, 将stdout赋值到一个文件中去。 因此,上面的命令行,可以如此执行:

cmd1 | cmd2 | tee file | cmd3

在预设上,tee会改写目标文件, 若你要改为追加内容的话,那可用-a参数选项。

基本上,pipe line的应用在shell操作上是非常广泛的。 尤其是在text filtering方面, 如,cat, more, head, tail, wc, expand, tr, grep, sed, awk...等等文字处理工具。 搭配起pipe line 来使用,你会觉得 command line 原来活得如此精彩的。 常让人有“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”之感...

好了,关于I/O Redirection的介绍就到此告一段落。 若日后,有空的话,在为大家介绍其他在shell上好玩的东西。

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:8月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:8月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:8月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:8月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:8月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:8月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:8月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:8月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:8月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:8月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:8月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:8月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:8月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:8月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:8月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:8月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:8月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:8月以前  |  398次阅读  |  详细内容 »
 相关文章
如何查看docker镜像里的文件 4年以前  |  5256次阅读
Shell语法快速入门 5年以前  |  2939次阅读
Shell命令在后台运行程序 5年以前  |  2871次阅读
Shell脚本编程30分钟入门 4年以前  |  1703次阅读
 目录