关于 xargs 参数被截断,tar 文件被覆盖的问题

时间:2022-04-28
本文章向大家介绍关于 xargs 参数被截断,tar 文件被覆盖的问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

问题:

目录下共 2W+ 个小文件:

$ find . -type f | wc -l  

20083  

如果我们这样打包,会爆出 "Argument list too long" 的错误:

$ tar zcf test.tar.gz *  

-bash: /bin/tar: Argument list too long  

这是由于 * 展开后参数长度超过系统参数 ARG_MAX 的限制

为了不报这种错误,我们考虑用find的参数扩展来试试:

$ find . -type f -name "120150_*" | xargs tar zcvf 120150.tar.gz  

这个执行下来没有报错,但是 120150.tar.gz 中并没有包含全部的文件:

$ gzip -d 120150.tar.gz && tar tf 120150.tar | wc -l  

3407  

Linux 有个系统参数,用来控制命令行下参数的长度(包含环境数据),这个参数是 ARG_MAX ,在正式环境上是 131072 (bytes) :

$ getconf ARG_MAX  

131072  

    凡是超过 131072 bytes 长度的参数都会被截断, * 分批 * 传给 xargs 后面的参数。所以我猜想,第二批参数列表产生的压缩包把第一批参数列表产生的压缩包覆盖掉了,第三批又把第二批覆盖掉了。。。实际上只有最后一次传进来的参数被打进了压缩包中。

解决办法:

先追加打包所有文件,再压缩:

FILE_NUM=$(find . -type f | wc -l)  
logger "$BID FILE_NUM = $FILE_NUM"  
if [[ $FILE_NUM -gt $FILE_TRANSFER_LIMIT ]];then  
  logger "FILE_NUM More than $FILE_TRANSFER_LIMIT"  
  # 先用tar创建一个空的tar包,"tar cf null.tar" 会报错:"tar: Cowardly refusing to create an empty archive"  
  tar uf ./$BID.tar  
  # 用xargs追加进去所有的文件,这次不用怕被截断了~  
  find . -name "${BID}_*" | xargs tar uf ./$BID.tar  
  # 然后再压缩  
  gzip ./$BID.tar  
else  
  logger "FILE_NUM Less than $FILE_TRANSFER_LIMIT"  
  tar zcf ./$BID.tar.gz "$BID"_*  
fi

其实 xargs 这些用法的区别有些类似于 http 协议中 " 幂等 " 的概念, tar cf 这种命令是不 " 幂等 " 的, rm 这类的命令则是 " 幂等 " 的,有兴趣的同事可以参考这个链接: http://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE#.E5.AE.89.E5.85.A8.E5.8F.8A.E5.B9.82.E7.AD.89.E6.96.B9.E6.B3.95