#!/usr/bin/perl
# The Missing Textutils, Ondrej Bojar, obo@cuni.cz
# http://www.cuni.cz/~obo/textutils
#
# 'autocat' is a unified replacement for 'cat', 'zcat', 'bzcat'.
# It can also cat files given in a filelist or a glob (wildcard expression),
# which is useful if the glob would expand to excessive number of arguments in
# your shell.
#
# $Id: autocat,v 1.3 2014-01-28 18:29:23 bojar Exp $

use strict;
use Getopt::Long;
use IPC::Open2;

my $fl = undef;
my @glob = ();
my $sort = 0;
my $prefix = undef;
GetOptions(
  "filelist|fl=s" => \$fl,
  "glob=s" => \@glob,
  "prefix=s" => \$prefix, # prefix each file with this line
  "sort" => \$sort, # sort the file list before catting
) or exit 1;

if (defined $prefix) {
  $prefix =~ s/\\n/\n/g;
  $prefix =~ s/\\t/\t/g;
}

my @fl = ();
if (defined $fl) {
  if ($fl eq "-") {
    *IN = *STDIN;
  } else {
    open IN, $fl or die "Can't read $fl";
  }
  while (<IN>) {
    chomp;
    push @fl, $_;
  }
  if ($fl ne "-") {
    close(IN);
  }
}

my @all = (@ARGV, (map {(glob($_));} @glob), @fl);
my @use;
if ($sort) {
  @use = sort {$a cmp $b} @all;
} else {
  @use = @all
}
foreach my $f (@use) {
  print $prefix."\n" if defined $prefix;
  runcat($f);
}

if (0 == scalar @use) {
  # just follow stdin
  print while <>;
}


sub runcat {
  my $f = shift;
  my $usef = $f;
  my $cmd;
  if ( -e $f ) {
    if ($f =~ /\.gz$/) {
      $cmd = "zcat";
    } elsif ($f =~ /\.bz2$/) {
      $cmd = "bzcat";
    } else {
      # run 'file' to eagerly uncompress even files without the .gz/.bz2 suffix
      my $chld_out; my $chld_in;
      my $pid = open2($chld_out, $chld_in, 'file', $f);
      my $ft = <$chld_out>;
      chomp $ft;
      close $chld_in;
      waitpid($pid,0);
      # file might not recognize some files!
      if ($ft =~ /gzip compressed data/) {
        $cmd = "zcat";
      } elsif ($ft =~ /bzip2 compressed data/) {
        $cmd = "bzcat";
      } else {
        $cmd = "cat";
      }
    }
  } elsif ( -e ($usef = $f.".gz") ) { # eagerly pick a compressed version
    $cmd = "zcat";
  } elsif ( -e ($usef = $f.".bz2") ) {
    $cmd = "bzcat";
  } else {
    die "Not found: $f";
  }
  my @args= ($cmd, $usef);
  system(@args);
}
