blackwolf has asked for the wisdom of the Perl Monks concerning the following question:

I'd like to get the original command line used to run a script. The goal is to pipe some output to a second instance of the script, similar to using open(P,"|-"), except that the new invocation will be at the end of a sequence of piped commands. I'd like to do something like: open( P, "| prog1 | prog2 | -" ) so that the original name and arguments of the script is preserved (it could be symlinked, and it's required that the script itself needs to know the name) but this generates a runtime whine of sh: - not found.

I've come up with a couple of really hacked ideas to implement this, but the easiest would involve getting the full command line by which the script was invoked, so I could run:

$originalcmdline = some magic code here ...; open( P, "| prog1 | prog2 | $originalcmdline" );
and pump data into P.

Anticipating at least one answer, doing something like $originalcmdline = "$0 " . join(' ',@ARGV); won't work - strings in @ARGV could contain whitespace, quotes, double quotes, backslashes, wildcard characters, etc, making safe reconstruction of the command line a real pain.

Any suggestions?

Replies are listed 'Best First'.
RE: Getting a script's original command line
by merlyn (Sage) on Jun 16, 2000 at 20:31 UTC
    Not much hope. $0 is a hint, not reliable, and @ARGV disappears as soon as someone messes with it. And the pipe-open is doing a fork, not a re-exec.

    Better rethink your strategy.

    -- Randal L. Schwartz, Perl hacker

Re: Getting a script's original command line
by mdillon (Priest) on Jun 16, 2000 at 20:35 UTC
    in general, i don't think this is possible. there is no way to do it in Perl, i believe. however, under GNU/Linux, you can read from /proc/self/cmdline to get the command line of the current process.

    the following worked for me under Linux 2.2:

    open CMDLINE, "/proc/self/cmdline"; print map { $_, $/ } <CMDLINE>; close CMDLINE;
    it still doesn't give you the exact command line though, just what was passed to exec. you would have to get the verbatim command line from the shell, and at least under BASH, it is not in %ENV.

    update: Randal correctly noted that the arguments from /proc/self/cmdline are NUL-separated, so the following works better:

    $/ = "\x000"; $\ = "\n"; open CMDLINE, "/proc/self/cmdline"; print for (<CMDLINE>); close CMDLINE;
      This is getting a little too nasty to implement portably, similar to the solutions I'd come up with. Portability is an issue, so the /proc/self/cmdline option's out.

      I think the best solution is Randal's "strategy rethink". What else did I have to do today, anyway? :)

Re: Getting a script's original command line
by NorthernDean (Initiate) on Sep 05, 2018 at 21:59 UTC

    Hi, found a relevant snippet on StackOverflow https://stackoverflow.com/questions/6156742/how-can-i-capture-the-complete-commandline-in-perl .

    There's a lot of extra verbiage there, but the key part was something like this:

    my $script_command = $0; foreach (@ARGV) { $script_command .= /\s/ ? " \'" . $_ . "\'" : " " . $_; }

    It seems to do the job, at least for what I needed. Perhaps this will help someone else...

      Hello NorthernDean and welcome to the monastery and to the wonderful world of Perl!

      thanks for your hint, but as merlyn said 18 years ago (ouch!) and as YourMother repeated it is not so reliable. The fact is that perl does not provide a methodo to inspect the original argument list and in this list you must consider also eventual module imported and perl switch.

      Our esteemed monk tobyink tried to mind this gap with a little XS module Devel::PL_origargv which you may find useful:

      # be aware of windows double quotes! perl -MDevel::PL_origargv -MData::Dumper -e "print Dumper [ Devel::PL_ +origargv->get ]" perlmonks 42 perl $VAR1 = [ 'perl', '-MDevel::PL_origargv', '-MData::Dumper', '-e', 'print Dumper [ Devel::PL_origargv->get ]', 'perlmonks', '42', 'perl' ];

      As you can see also the oneliner is included in arguments: infact is an argument passed to perl -e and the same pass if you run a separate program: the filename is included in argument passed to perl.

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Getting a script's original command line
by cleen (Pilgrim) on Jun 16, 2000 at 22:18 UTC
    Mabye Im looking at the question wrong here, but uhh... wouldnt somthing like this work?
    #!/usr/local/bin/perl print "Command: $0 @ARGV\n"; open(P, "echo hi |echo @ARGV |cat @ARGV|"); while (<P>) { print $_ }
Re: Getting a script's original command line
by Aighearach (Initiate) on Jun 17, 2000 at 01:28 UTC
    Why don't you just save the original in a temp file? $0 can get messed with, but if you read it first thing, and write it to a file, then you can just read the file. It works for PIDs, anyway...
    Paris Sinclair    |    4a75737420416e6f74686572
    pariss@efn.org    |    205065726c204861636b6572
    I wear my Geek Code on my finger.