【问题标题】:find results piped to zcat and then to head查找结果通过管道传输到 zcat,然后传输到 head
【发布时间】:2011-03-21 09:36:28
【问题描述】:

我正在尝试在许多 gzip 压缩的 csv 文件中搜索某个字符串,该字符串位于第一行,我的想法是通过组合 find、zcat 和 head 来获取每个文件的第一行。但我无法让他们一起工作。

$find . -name "*.gz" -print | xargs zcat -f | head -1
20051114083300,1070074.00,0.00000000
xargs: zcat: terminated by signal 13

example file:
$zcat 113.gz | head
20050629171845,1069335.50,-1.00000000
20050629171930,1069315.00,-1.00000000
20050629172015,1069382.50,-1.00000000
 .. and 2 milion rows like these ...

虽然我通过编写 bash 脚本、遍历文件并写入临时文件来解决问题,但如果知道我做错了什么、如何做以及是否还有其他方法,那就太好了关于它。

【问题讨论】:

    标签: bash find pipe zcat unix-head


    【解决方案1】:
    zcat -r * 2>/dev/null | awk -vRS= -vFS="\n" '{print $1}'
    

    【讨论】:

      【解决方案2】:

      它按您的要求工作。

      head 完成了它的工作,打印了一行,然后退出了。 zcat 然后在 xargs 的支持下运行,试图写入一个封闭的管道并收到一个致命的 SIGPIPE。孩子死了,xargs 报告了原因。

      要获得所需的行为,您需要 find -exec ... 构造或自定义 zhead 以提供给 xargs。

      添加了我在冰箱后面发现的垃圾代码

      #!/usr/bin/python
      
      """zhead - poor man's zcat file... | head -n
         no argument error checking, prefers to continue in the face of
         IO errors, with diagnostic to stderr
      
         sample usage: find ... | xargs zhead.py -1"""
      
      import gzip
      import sys
      
      if sys.argv[1].startswith('-'):
          nlines = int(sys.argv[1][1:])
          start = 2
      else:
          nlines = 10
          start = 1
      
      for zfile in sys.argv[start:]:
          try:
              zin = gzip.open(zfile)
              for i in range(nlines):
                  line = zin.readline()
                  if not line:
                      break
                  print line,
          except Exception as err:
              print >> sys.stderr, zfile, err
          finally:
              try:
                  zin.close()
              except:
                  pass
      

      它在大约一分钟内处理了 /usr/share/man 中的 10k 个文件。

      【讨论】:

      • 很好的解释,我希望我能支持你,当我达到 15reps 时我会回来。
      • 很高兴能提供帮助。不要担心投票,这不是我这样做的原因(丹尼斯威廉姆森得到了我的投票,因为它更好)。
      【解决方案3】:

      你应该会发现这会起作用:

      find . -name "*.gz" | while read -r file; do zcat -f "$file" | head -n 1; done
      

      【讨论】:

      • 工作完美,谢谢。不知道你可以使用 while 和那样阅读,我会记住的。
      • 你也可以使用:for f in *.gz; do zcat $f | head -n 1; done
      • @arekolek:除非您使用shopt -s globstar; for f in **/*.gz,否则它不是递归的,而find 是递归的,除非您使用-maxdepth 限制它。
      【解决方案4】:

      如果您安装了 GNU Parallel http://www.gnu.org/software/parallel/

      find . -name '*.gz' | parallel 'zcat {} | head -n1'
      

      http://www.youtube.com/watch?v=OpaiGYxkSuQ观看 GNU Parallel 的介绍视频

      【讨论】:

        猜你喜欢
        • 2017-05-11
        • 2015-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多