有没有将zcat和cat透明结合的工具?


70

处理日志文件时,某些文件最终要归为压缩文件,logrotate而其他文件则不然。因此,当您尝试这样的事情时:

$ zcat *

您最终得到如下命令行zcat xyz.log xyz.log.1 xyz.log.2.gz xyz.log.3.gz

gzip: xyz.log: not in gzip format

是否有一个工具可以获取神奇的字节(类似于其file工作原理),并根据结果使用zcatcat取决于结果,以便grep例如将输出通过管道传输到?

注意:我知道我可以编写脚本,但是我在问是否已经有工具。

Answers:


41

zless

似乎很可惜zcat,因为libz有一个API支持透明地读取压缩文件和未压缩文件。但是联机帮助页确实说zcat等效于gunzip -c


谢谢您的替代选择。我本来可以想到的,不是吗?;) ... 那好吧。点选,+ 1和接受(也是因为您的代表比另一个应答者少)。
0xC0000022L13年

惊人。帮了我很多忙,多年来我一直在使用Shell脚本来解决这个问题...或者可怕的Perl脚本... awstats使用的日志解析合并...现在我知道这个了不起的工具。谢谢。
Luciano Andress Martini

98

尝试使用-f--force

zcat -f -- *

因为zcat这只是一个运行的简单脚本

exec gzip -cd "$@"

有很长的选择会转化为

exec gzip --stdout --decompress "$@"

并且,根据man gzip(强调我的):

-f --force
      即使文件具有多个链接也强制进行压缩或解压缩
      或者相应的文件已经存在,或者压缩数据是否为
      从终端读取或写入终端。如果输入数据不是格式
      由gzip识别,并且如果还提供了--stdout选项,请复制
      输入数据而不更改为标准输出:让zcat表现为cat

也:

这样我就可以将输出传递grep给例如

您可以使用zgrep

zgrep -- PATTERN *

尽管请参阅下面的斯特凡评论。


1
谢谢,这是该zless解决方案的一个有趣替代方案。不错,+ 1。
0xC0000022L13年

6
请注意,zlesszgrep都是可以调用的脚本gzip -cdfq(即zcat -fq)。
斯特凡Chazelas

9

我完全出于相同的目的:

{ cat /var/log/messages ; zcat /var/log/messages*.gz ; }| grep something | grep "something else" ....

我喜欢这种方法,因为它需要最少的时间来培训同事。如果日志消息中的时间戳具有排序友好的时间戳,则此功能特别有用。
Thomas L Holaday '18

优秀的方法。谢谢。
米洛什Đakonović

7

有一个名为zutils的ztools(zcat,zgrep,..)的直接替代品,它将所有解压缩工具独立于后端。因此,使用同一命令可以透明地读取普通,lzma,gzipped,xz文件。

它可以在debian wheezy或更高版本中使用,可能也可以在redhat / centos中使用。

该项目的页面在这里nongnu.org

博客文章,在此说明util的用法(noone.org


3

在RHEL 5.x(zcat是二进制文件)中,这可以正常工作。它在zcat是脚本的RHEL 6.x(和Ubuntu 12.x)中失败。这用来很好地工作。

我根本不会使用zcat,但zgrep也无法正确处理未压缩的文件。


2

按时间顺序打开压缩和未压缩的文件。

ls -v syslog* | tac | xargs zcat -f | less

它给出了错误的顺序并带有十多个日志文件(syslog.10.gz ...)
Vanni

接得好。-v应该解决该问题。
瑞安

ls -rv避免tac。对于日志文件,less $(ls -rv syslog*)与你LESSOPEN的环境变量设置不当效果很好。您可以跨文件搜索,esc-n以查找下一个匹配项,而忽略文件边界。
彼得·科德斯

随着zshzcat -f syslog*(nOn)
斯特凡Chazelas

如果您将日志旋转设置为第二天压缩,则此方法将
无效

1

包装纸呢?

$ cat xcat.sh 
#!/bin/bash

for i in $@;do 
        [ ! -z "$(file -i $i | grep "gzip")" ] && zcat $i || cat $i
done

$ bash xcat.sh plain.txt gzipped_text.gz

0

复制并粘贴(或将其放在~/.bashrc文件末尾)此bash函数:

logs() { zcat -f $(ls -rv "$1"*) | less; }

现在,您可以键入例如logs /var/log/sysloglogs /var/log/nginx/access.log看到所有系统日志nginx的从最旧到最新的日志信息与

然后,您可以搜索一些打字/something,打n下一个


0

有一个漂亮的perl脚本可以做到这一点。这是从AWStats的项目logresolvemerge.pl:http://www.awstats.org/docs/awstats_tools.html

Logresolvemerge允许您从特定来源获取一个按日期排序的唯一输出日志文件:

  • 它可以读取多个输入日志文件
  • 它可以读取.gz / .bz2日志文件

    输出在STDOUT上,因此您可以在其他过程中很好地利用它。


  • 0

    在@Ryan的答案的基础上,以下代码将获取按字母顺序排序的所有“ rolled”文件,然后获取当前文件,解压缩它们(如果需要)以及less它们:

    cat <(ls mylog.log-* | sort) <(ls mylog.log) | xargs zcat -f | less

    或者,如果您希望将它们作为连续流全部获取,则可以将tail它们进行处理,并有选择地将其通过管道传输到另一个进程

    cat <(ls mylog.log-* | sort | xargs zcat -f) <(tail -f -n +0 mylog.log)

    我应该注意,这是为每天循环的日志而设计的,日期附加在文件末尾。如果您以其他格式记录我们,则必须修改cat语句的第一部分以适应。

    By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
    Licensed under cc by-sa 3.0 with attribution required.