chronic: With -v, flush stdout after printing "STDERR" header
[moreutils.git] / zrun
blob98d1445a5f8106f04be690f85d802a7f6decfd13
1 #!/usr/bin/perl
3 =head1 NAME
5 zrun - automatically uncompress arguments to command
7 =head1 SYNOPSIS
9 zrun command file.gz [...]
11 =head1 DESCRIPTION
13 Prefixing a shell command with "zrun" causes any compressed files that are
14 arguments of the command to be transparently uncompressed to temp files
15 (not pipes) and the uncompressed files fed to the command.
17 This is a quick way to run a command that does not itself support
18 compressed files, without manually uncompressing the files.
20 The following compression types are supported: gz bz2 Z xz lzma lzo
22 If zrun is linked to some name beginning with z, like zprog, and the link is
23 executed, this is equivalent to executing "zrun prog".
25 =head1 BUGS
27 Modifications to the uncompressed temporary file are not fed back into the
28 input file, so using this as a quick way to make an editor support
29 compressed files won't work.
31 =head1 AUTHOR
33 Copyright 2006 by Chung-chieh Shan <ccshan@post.harvard.edu>
35 =cut
37 use warnings;
38 use strict;
39 use IO::Handle;
40 use File::Spec;
41 use File::Temp qw{tempfile};
43 my $program;
45 if ($0 =~ m{(?:^|/)z([^/]+)$} && $1 ne 'run') {
46 $program = $1;
47 if (! @ARGV) {
48 die "Usage: z$1 <args>\nEquivalent to: zrun $1 <args>\n";
51 else {
52 $program = shift;
53 if (! @ARGV) {
54 die "Usage: zrun <command> <args>\n";
58 my @argument;
59 my %child;
60 foreach my $argument (@ARGV) {
61 if ($argument =~ m{^(.*/)?([^/]*)\.(gz|Z|bz2|xz|lzo|lzma)$}s) {
62 my $suffix = "-$2";
63 my @preprocess = $3 eq "bz2" ? qw(bzip2 -d -c) :
64 $3 eq "xz" ? qw(xz -d -c) :
65 $3 eq "lzo" ? qw(lzop -d -c) :
66 $3 eq "lzma" ? qw(lzma -d -c) : qw(gzip -d -c);
68 my ($fh, $tmpname) = tempfile(SUFFIX => $suffix,
69 DIR => File::Spec->tmpdir, UNLINK => 1)
70 or die "zrun: cannot create temporary file: $!\n";
72 if (my $child = fork) {
73 $child{$child} = $argument;
74 $argument = $tmpname;
76 elsif (defined $child) {
77 STDOUT->fdopen($fh, "w");
78 exec @preprocess, $argument;
80 else {
81 die "zrun: cannot fork to handle $argument: $!\n";
84 push @argument, $argument;
87 while (%child and (my $pid = wait) != -1) {
88 if (defined(my $argument = delete $child{$pid})) {
89 if ($? & 255) {
90 die "zrun: preprocessing for $argument terminated abnormally: $?\n";
92 elsif (my $code = $? >> 8) {
93 die "zrun: preprocessing for $argument terminated with code $code\n";
98 my $status = system $program ($program, @argument);
99 if ($status & 255) {
100 die "zrun: $program terminated abnormally: $?\n";
102 else {
103 my $code = $? >> 8;
104 exit $code;