[Linux]如果管道被接受方关闭
授权方式:署名,非商业用途,保持一致,转载时请务必以超链接(http://www.fwolf.com/blog/post/328)的形式标明文章原始出处和作者信息及本声明。linux shell中的管道|是非常方便的功能,可以将一个程序的输出作为另外一个程序的输入,这样我们可以将多个命令“拼”在一起,省去了临时文件的繁琐。windows中也有类似的用法,比如dir |more,学过dos命令的应该都知道吧。
既然是管道,那么就有一个入口和一个出口,各自对应一个应用程序,正常的情况下,入口应用程序的输出应当被出口应用程序全部接受,但在一些特殊情况,出口应用程序会提前关闭管道,比如在查询svn的更新日志,只取前己行的时候:
$ svn log |head
------------------------------------------------------------------------
r137 | Fwolf | 2007-05-28 13:38:47 +0800 (Mon, 28 May 2007) | 4 lines
更新记录。。。
svn: Write error: Broken pipe
由于head只需要用到输入的前10行(默认行数,也可由用户指定),再接收剩下的输出也是多余,便提前关闭了管道,管道入口的应用程序svn发现之后,便报错退出了。在这个例子中,错误信息非常清楚,但不是所有应用程序都这样的,比如下面这个:
$ find . -name "*rc" |xargs -i cat {}|head -1
[Desktop]
xargs: cat: terminated by signal 13
错误信息似乎并不太好理解,实际上它的意思是:xargs发现它的子进程cat由于信号13被中止了。由于xargs本身属于循环操作,发现错误之后就停止了循环,这是其一;信号13是在cat试图向一个已关闭的pipe管道中写数据的时候,系统产生的,cat收到之后就停止了。类似于在cat输出的过程中,用户按下ctrl+c的效果。
如何避免这种问题呢?很简单,管道后面使用不会提前关闭管道的程序即可,尤其是结合xargs使用的时候,它发现出错就不继续了。比如要用到head可以这样:
$ cat file |head -1
虽然cat仍然会被signal 13关闭,但bash是不会报错的,所以也只能针对一个文件进行操作,即使是使用了通配符也只能head到第一个文件。如果要加上对文件的遍历,可以用到for:
$for file in .*rc;do cat $file |head -1;done
cat依然会被关闭,但是for不会理会它,继续循环。head也可以直接指定文件名,这样我们就可以抛开cat了:
$find . -name "*rc" |xargs -i head -n1 {}
个人认为这是一种最完美的解决方式,即可以用到find强大的搜索指令,还不会涉及到管道的问题。不过如果文件名没有什么特殊要求,还有一种更简单的方式:
$head -n1 .*rc
在head的参数中直接用通配符指定文件,呵呵。
参考:
No tags for this post.
Save to Browser Favorites
Ask
backflip
blinklist
BlogBookmark
Bloglines
BlogMarks
Blogsvine
BUMPzee!
CiteULike
co.mments
Connotea
del.icio.us
DotNetKicks
Digg
diigo
dropjack.com
dzone
Facebook
Fark
Faves
Feed Me Links
Friendsite
folkd.com
Furl
Google
Hugg
Jeqq
Kaboodle
linkaGoGo
LinksMarker
Ma.gnolia
Mister Wong
Mixx
MySpace
MyWeb
Netvouz
Newsvine
PlugIM
popcurrent
Propeller
Reddit
Rojo
Segnalo
Shoutwire
Simpy
sk*rt
Slashdot
Sphere
Sphinn
Spurl.net
Squidoo
StumbleUpon
Technorati
ThisNext
Webride
Windows Live
Yahoo!
Email This to a Friend
If you like this then please subscribe to the
June 4th, 2007 at 12:16:45
感谢你回答我的问题。你的答案有些深 :) 找机会我请你再解释一下。
我原始的问题是有一个目录中有一些mp3,我需要重新压缩它们
当我用
的时候,出现你说的这个错误
我觉得这是因为我lame压缩重新压缩出来的文件名称后缀也是.mp3和原有文件重复了所以系统拒绝工作
如果我把该目录下的mp3文件都改名为.test,谁能告诉我在命令行里面怎么改,我是用的xfce的thunar改的
那么我再次运行上面的命令就可以了。但是注意,要明确告诉lame你输入的.test文件就是mp3文件,否则它当成输入的是wav了吧 ,所以你要加一个参数 –mp3input,这些 man lame就都知道可
请问有没有更好的解决方法?
[Reply]
June 5th, 2007 at 1:36:04
把mp3文件放到一个目录中,然后在另外的一个目录里面进行操作
这样生成的文件就在当前目录中,不会和原文件冲突
就像:
或者用find替代ls,不管怎样,改名不是个好主意
[Reply]