查看原文
其他

find和xargs连用虽好,但用起来要小心哦~

2017-02-19 奔跑的天地本无心 生信媛

上一篇公众号文章,前面讲了很多故事和八卦,但通篇最重要的一点就是用rm -fr softlinkrm -fr softlink/根本就是两个效果完全不同的命令,希望能给自动补全党带来一点点启示意义。今天的一条导致危险的命令也和rm -fr有关,但是主角不是它,是xargs


find . -name "*.fasta" | xargs wc -l


比如我们在linux shell tricks for bioinformatics I里面提到的一条指令,这行命令可以统计当前文件夹下,所有的fasta文件的行数。xargs在里面的意义就是将fasta文件的名字,一个一个地传递给wc -l命令。


那我们再看看下面的一条命令:

不安全命令,非错误命令:

find . -maxdepth 1 -name "*.txt" | xargs rm -fr 

这个命令也许会达到你的目的。但是,一次能够正确执行你想要的操作,并不代表这个命令每次都能如你所愿。并且事实上,这条命令是非常危险的!


小伙伴请想象一下这个场景: 你辛辛苦苦做了三年生信,好容易攒了很多代码和Pipeline。把这些东西放在你的干活的电脑的Code和Pipeline的文件夹。你师兄毕业了,好心的他决定把他的代码给你,他拷给你好多文件夹,叫Zhaocheng Code,Zhaocheng Pipeline, Zhaocheng BlaBla等等。因为个人喜好缘故,他喜欢用空格来分隔文件名里的字符串。然后你点进去一看,全部是perl(破)代码。作为python爱好者的你,决定将它弃之如敝履。


来,跟着我的操作做一个测试。


find ./ -maxdepth 1 -name "*Zhaocheng*" | xargs rm -fr 


运行完这句shell命令之后,你发现你想删掉的zhaocheng Code,zhaocheng Pipeline, zhaocheng BlaBla文件夹还在,你自己积攒的Code, Pipeline反而被删了! 此刻你的内心,想必一定是一万头神兽飘过。稍微平静一点之后呢,我们来试图理解一下其中的原因。


前面的都是些不痛不痒的,下面的几句话希望大家能够牢记。


1. xargs的默认定界符是空格。

2. 空字符(Null character)又称结束符,缩写NUL,是一个数值为0的控制字符。编程语言会自动在字符串结尾加上结束符,不需由程序员自己打上去。


当你find到了Zhaocheng Code之后,通过xargs传递给rm -fr时,因为xargs的默认定界符是空格。xargs会将Zhaocheng Code拆分成rm -fr Zhaochengrm -fr Code。然后这就是为什么你想删掉的没有删掉,而不想删的却误删了的原因。这种情况不一定每次都能碰到,但是有一种情况风险是非常高的。就是删除文献的时候,你想一下,文献的题目都是空格分开的,如果某一个字段正好跟你的文件夹重名,那就真的哔了狗了。


那这么说来,这个命令是不是不能用了啊。


其实还是能够用的。只需要指定定界符,将定界符制定为字符串的结束符null字符串就行。这样可以在xargs命令中,以null字符串(\0),也就是结束符来分隔输入参数,但find找到了Zhaocheng Code这个文件夹之后,是将这个名称整体地传递给rm -fr Zhaocheng Code来执行,这样就规避了空格作为定界符带来的风险。命令如下:


find  ./ -maxdepth 1 -name "*Zhaocheng*" -print0  | xargs -0  rm -fr


也有其它的方法:

find  ./ -maxdepth 1 -name "*Zhaocheng*" | xargs -I {}  rm -fr {}

或者

find . -maxdepth 1 -name "*Zhaocheng*"   -exec rm -fr {} \;


这样就能规避风险,当然方法还有很多很多,比如说,先将文件或者文件名里的空格全部替换为下划线,然后再执行操作。虽然这方法笨了点,但是非常稳妥。


最后还有一个建议,就是文件夹或者文件名里不要人为地加入空格,强迫症患者看着难受,空格全部用下划线代替。


PS: 二月已经跑步120公里,加油,奔跑的天地本无心!


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存