http://qs1969.pair.com?node_id=139379

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

Hi Monks,

I looked at some perl script at work and
I noticed that some of them use this ...

#!/bin/sh -- perl eval 'exec perl -S $0 ${1+"$@"}' if 0;

... is this safe ... am I just
being paranoid?

Thanks

Replies are listed 'Best First'.
Re: #! question
by VSarkiss (Monsignor) on Jan 17, 2002 at 03:57 UTC

    This is actually for systems that don't support shebang execution.

    If you look very carefully, you'll notice that the eval string is a shell command, not Perl. On systems that don't have shebang, this gets handed to a shell, which hopefully has Perl in its PATH. That shell then exec's perl -S script args where the name was $0 and the args, if any, came from the ${1+"$@"}.

    Now, when it does get handed to Perl, the if 0 on the next line stops it from doing the eval (of course, the shell is line-oriented and never sees the if!) This would also happen if the system started supporting shebang execution and the file was handed to Perl directly in the first place.

    Nasty but effective, no?

      Just in addition to VSarkiss' excellent explanation, I thought I would just add that this is discussed in the perlrun man page, specifically under the -S switch.

       

      perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Re: #! question
by Chmrr (Vicar) on Jan 17, 2002 at 03:32 UTC

    The purpose of this to ensure that it runs correctly on machines which have a broken shell which does not respect the #! line. Thus, one can run it as ./script.pl or perl script.pl and it wull function identically.

    It does look rather strange, though, as most versions that do this have #!perl as the first line -- this one seems to be forcing the shell to exec it explicitly. Strange, but I see no reason why it wouldn't work. It might confuse some webservers that arn't overly smart, though.

    Update: I sit corrected. I'd never seen this construction used in that way before, only for broken-shell prevention.

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

      Actually no, not really. The purpose of this is to set a perl script to run on a given machine without knowing where the binary lives, with the limitation that it be in your PATH.

      UPDATE: Further, as covered elsewhere #! is the kernel's responsibility not the shell's.

      --
      perl -pe "s/\b;([st])/'\1/mg"