#!/usr/bin/perl -l =head1 NAME curiouscat - grep the output of a command, only printing stdout/stderr if match =head1 SYNOPSIS cgrep [-v] [-f PATTERNFILE | PATTERN ] COMMAND... =head1 DESCRIPTION curiouscat runs a command, buffering the output from both standard out and standard error, looking for a matching pattern. If a matching pattern is found, stdout and stderr are printed and curiouscat exits with the exit code of COMMAND. If the -v switch is passed, curiouscat switches into reverse mode where it will print if there are any lines not matching PATTERN. =head1 AUTHOR Copyright 2010, 2013 by Collabora Limited, written by Tollef Fog Heen Licensed under the GNU GPL. =cut use warnings; use strict; use IPC::Run qw( start pump finish timeout ); $|=1; my $reverse = 0; my @patterns = (); my $patternfile; use Getopt::Long; GetOptions("v" => \$reverse, "f=s" => \$patternfile) || die "usage: curiouscat [-v] [-f PATTERNFILE | PATTERN ] COMMAND...\n"; if (defined $patternfile) { my $p; open $p, "<", $patternfile or die "Can't open $patternfile: $!"; chomp(@patterns = <$p>); } else { @patterns = (shift @ARGV); } my @command = @ARGV; my ($in, $out, $err); my $h = IPC::Run::start \@command, \*STDIN, \$out, \$err; $h->finish; if ($reverse) { for my $line (split(/$\//, $out), split(/$\//, $err)) { my $nomatch = 1; for my $p (@patterns) { if ($line =~ /$p/m ) { $nomatch = 0; last; } } if ($nomatch) { print STDOUT $out; print STDERR $err; last; } } } else { for my $p (@patterns) { if ($out =~ /$p/m or $err =~ /$p/m) { print STDOUT $out; print STDERR $err; } } } exit $h->result or 0;