http://qs321.pair.com?node_id=151267

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

How do i change the interpreter line to #!/usr/local/bin/perl in all perl scripts in the current directory thanks a million :)))))

Edit kudra, 2002-03-15 Changed title to describe problem

Replies are listed 'Best First'.
Re: question about perl
by Trimbach (Curate) on Mar 13, 2002 at 00:37 UTC
    If all your scripts are in one directory, and they all end with (for example) .pl, you can do it in one line from a UNIX shell:

    user% perl -pi.bak -e 'BEGIN{undef $/};s[^#\!/usr/local/bin/perl][#\!/usr/bin/perl]' *.pl

    One-liners rock!

    Gary Blackburn
    Trained Killer

    Correction: Code enhanced thanks to mahi

      It is true that your script will replace the Perl path within the shebang string, but it will also replace it if the same string is anywhere inside the script.
      perl -pi.bak -e 's[^#!/usr/local/bin/perl][#!/usr/bin/perl]' *.pl
      This one should guarantee that the replacement happens only at the beginning of a string. To ensure that the replacement is carried out only once in each script, though, one more check is needed.
      perl -pi.bak -e 'BEGIN{$c=@ARGV};s[^#!/usr/local/bin/perl][#!/usr/bin/ +perl] && $c-- if $c> @ARGV' *.pl
      which translates roughly into
      #!/usr/bin/perl -w -i.bak use strict our $count=@ARGV; while (<>) { if ($count > @ARGV) { s[^#!/usr/local/bin/perl][#!/usr/bin/perl]; $count--; } print; }
        Yeah, I know about the "anywhere in the script" thingy, but
        perl -pi.bak -e 's[^#!/usr/local/bin/perl][#!/usr/bin/perl]' *.pl
        yields a "/usr/local/bin/perl][: Event not found." error on my Perl 5.6.1 system, which is why I didn't post my original answer with an anchor metacharacter. Don't really know why the "^#!" is freaking out the regex, but on further examination it looks like the ! has to be escaped. I've corrected the code in my original post to compensate.

        And all of this:

        perl -pi.bak -e 'BEGIN{$c=@ARGV};s[^#!/usr/local/bin/perl][#!/usr/bin/ +perl] && $c-- if $c> @ARGV' *.pl
        can replaced with this:
        perl -pi.bak -e 'BEGIN{undef $/};s[^#\!/usr/local/bin/perl][#\!/usr/bi +n/perl]' *.pl
        ...which at least saves some typing, and is a bit more understandable besides. :-D

        Gary Blackburn
        Trained Killer

        Update: The exclamation mark needs escaping because I'm using tcsh, a csh-style shell. Anyone using a different type of shell (such as bash or other Bourne-type shell) shouldn't have to escape the ! at all. What a pain in the butt... :-(

Re: question about perl
by Ryszard (Priest) on Mar 13, 2002 at 00:10 UTC
    A quick (untested) hack:
    #!/usr/bin/perl -w use strict; my @files = `find . -name "*.pl"`; foreach my $file (@files) { local*FH; open(FH, ">$file"); my @contents = <FH>; $contents[0]="#!/usr/local/bin/perl -w"; print FH $_ foreach (@contents); close FH; }

    Yup, I'm aware of the bad practice in this script, however, its just a quick hack.

    NB: I've taken the liberty to add warnings (-w) to your shebang, and it may break your scripts, although, it shouldnt.. :-)

    Update: Fixed typo as per defyance's comment. Please note the "untested" disclaimer.

      If you change this:

      my @files = `find . -name "*.pl";

      To this:

      my @files = `find . -name "*.pl"`;

      It will work, but make all of your *.pl files say nothing but #!/usr/local/bin/perl. Thought I'd point that out.

      -- Yes, I am a criminal. My crime is that of defyance.
Re: question about perl
by defyance (Curate) on Mar 12, 2002 at 23:51 UTC
    If I'm understanding what you are saying, you have a whole bunch of perl scripts, and you need to change one line (#!/usr/bin/perl??) to #!/usr/local/bin/perl on all of the perl files in a dir? If that is the case technically you could write a perl script to do it. It wouldn't take long, or much to hack one out. Is my understanding correct?

    -- Yes, I am a criminal. My crime is that of defyance.
      I had some thoughts about this very subject posted to a different forum.

      We spend a lot of effort with modules, verifying that all files are present, they work, etc. before putting them live.

      What about their poor relations, the scripts? A script writer could implement tests in an equivalent of make test. The install step could copy to cgi-bin or wherever the script needs to go, changing the shebang line in the process, having worked out where perl lives.

      Could Extutils::MakeMaker be used to do this, or is this too hard-coded for modules and h2xs?

        Check the only entry in my CPAN directory for my script that does shell-to-Perl translation. It shows how to hack the shebang line during installation, and also shows tests for the script.

        -- Randal L. Schwartz, Perl hacker