1 eval 'exec perl -x -S "$0" ${1+"$@"}' 2 if 0; # In case running under some shell 3 4require 5; 5use Getopt::Std; 6use Config; 7 8$0 =~ s|.*[/\\]||; 9 10my $usage = <<EOT; 11Usage: $0 [-h] 12 or: $0 [-w] [-u] [-a argstring] [-s stripsuffix] [files] 13 or: $0 [-w] [-u] [-n ntargs] [-o otherargs] [-s stripsuffix] [files] 14 -n ntargs arguments to invoke perl with in generated file 15 when run from Windows NT. Defaults to 16 '-x -S "%0" %*'. 17 -o otherargs arguments to invoke perl with in generated file 18 other than when run from Windows NT. Defaults 19 to '-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9'. 20 -a argstring arguments to invoke perl with in generated file 21 ignoring operating system (for compatibility 22 with previous pl2bat versions). 23 -u update files that may have already been processed 24 by (some version of) pl2bat. 25 -w include "-w" on the /^#!.*perl/ line (unless 26 a /^#!.*perl/ line was already present). 27 -s stripsuffix strip this suffix from file before appending ".bat" 28 Not case-sensitive 29 Can be a regex if it begins with `/' 30 Defaults to "/\.plx?/" 31 -h show this help 32EOT 33 34my %OPT = (); 35warn($usage), exit(0) if !getopts('whun:o:a:s:',\%OPT) or $OPT{'h'}; 36$OPT{'n'} = '-x -S "%0" %*' unless exists $OPT{'n'}; 37$OPT{'o'} = '-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9' unless exists $OPT{'o'}; 38$OPT{'s'} = '/\\.plx?/' unless exists $OPT{'s'}; 39$OPT{'s'} = ($OPT{'s'} =~ m#^/([^/]*[^/\$]|)\$?/?$# ? $1 : "\Q$OPT{'s'}\E"); 40 41my $head; 42if( defined( $OPT{'a'} ) ) { 43 $head = <<EOT; 44 \@rem = '--*-Perl-*-- 45 \@echo off 46 perl $OPT{'a'} 47 goto endofperl 48 \@rem '; 49EOT 50} else { 51 $head = <<EOT; 52 \@rem = '--*-Perl-*-- 53 \@echo off 54 if "%OS%" == "Windows_NT" goto WinNT 55 perl $OPT{'o'} 56 goto endofperl 57 :WinNT 58 perl $OPT{'n'} 59 if NOT "%COMSPEC%" == "%SystemRoot%\\system32\\cmd.exe" goto endofperl 60 if %errorlevel% == 9009 echo You do not have Perl in your PATH. 61 if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul 62 goto endofperl 63 \@rem '; 64EOT 65} 66$head =~ s/^\t//gm; 67my $headlines = 2 + ($head =~ tr/\n/\n/); 68my $tail = "\n__END__\n:endofperl\n"; 69 70@ARGV = ('-') unless @ARGV; 71 72foreach ( @ARGV ) { 73 process($_); 74} 75 76sub process { 77 my( $file )= @_; 78 my $myhead = $head; 79 my $linedone = 0; 80 my $taildone = 0; 81 my $linenum = 0; 82 my $skiplines = 0; 83 my $line; 84 my $start= $Config{startperl}; 85 $start= "#!perl" unless $start =~ /^#!.*perl/; 86 open( FILE, $file ) or die "$0: Can't open $file: $!"; 87 @file = <FILE>; 88 foreach $line ( @file ) { 89 $linenum++; 90 if ( $line =~ /^:endofperl\b/ ) { 91 if( ! exists $OPT{'u'} ) { 92 warn "$0: $file has already been converted to a batch file!\n"; 93 return; 94 } 95 $taildone++; 96 } 97 if ( not $linedone and $line =~ /^#!.*perl/ ) { 98 if( exists $OPT{'u'} ) { 99 $skiplines = $linenum - 1; 100 $line .= "#line ".(1+$headlines)."\n"; 101 } else { 102 $line .= "#line ".($linenum+$headlines)."\n"; 103 } 104 $linedone++; 105 } 106 if ( $line =~ /^#\s*line\b/ and $linenum == 2 + $skiplines ) { 107 $line = ""; 108 } 109 } 110 close( FILE ); 111 $file =~ s/$OPT{'s'}$//oi; 112 $file .= '.bat' unless $file =~ /\.bat$/i or $file =~ /^-$/; 113 open( FILE, ">$file" ) or die "Can't open $file: $!"; 114 print FILE $myhead; 115 print FILE $start, ( $OPT{'w'} ? " -w" : "" ), 116 "\n#line ", ($headlines+1), "\n" unless $linedone; 117 print FILE @file[$skiplines..$#file]; 118 print FILE $tail unless $taildone; 119 close( FILE ); 120} 121__END__ 122 123=head1 NAME 124 125pl2bat - wrap perl code into a batch file 126 127=head1 SYNOPSIS 128 129B<pl2bat> B<-h> 130 131B<pl2bat> [B<-w>] S<[B<-a> I<argstring>]> S<[B<-s> I<stripsuffix>]> [files] 132 133B<pl2bat> [B<-w>] S<[B<-n> I<ntargs>]> S<[B<-o> I<otherargs>]> S<[B<-s> I<stripsuffix>]> [files] 134 135=head1 DESCRIPTION 136 137This utility converts a perl script into a batch file that can be 138executed on DOS-like operating systems. This is intended to allow 139you to use a Perl script like regular programs and batch files where 140you just enter the name of the script [probably minus the extension] 141plus any command-line arguments and the script is found in your B<PATH> 142and run. 143 144=head2 ADVANTAGES 145 146There are several alternatives to this method of running a Perl script. 147They each have disadvantages that help you understand the motivation 148for using B<pl2bat>. 149 150=over 151 152=item 1 153 154 C:> perl x:/path/to/script.pl [args] 155 156=item 2 157 158 C:> perl -S script.pl [args] 159 160=item 3 161 162 C:> perl -S script [args] 163 164=item 4 165 166 C:> ftype Perl=perl.exe "%1" %* 167 C:> assoc .pl=Perl 168 then 169 C:> script.pl [args] 170 171=item 5 172 173 C:> ftype Perl=perl.exe "%1" %* 174 C:> assoc .pl=Perl 175 C:> set PathExt=%PathExt%;.PL 176 then 177 C:> script [args] 178 179=back 180 181B<1> and B<2> are the most basic invocation methods that should work on 182any system [DOS-like or not]. They require extra typing and require 183that the script user know that the script is written in Perl. This 184is a pain when you have lots of scripts, some written in Perl and some 185not. It can be quite difficult to keep track of which scripts need to 186be run through Perl and which do not. Even worse, scripts often get 187rewritten from simple batch files into more powerful Perl scripts in 188which case these methods would require all existing users of the scripts 189be updated. 190 191B<3> works on modern Win32 versions of Perl. It allows the user to 192omit the ".pl" or ".bat" file extension, which is a minor improvement. 193 194B<4> and B<5> work on some Win32 operating systems with some command 195shells. One major disadvantage with both is that you can't use them 196in pipelines nor with file redirection. For example, none of the 197following will work properly if you used method B<4> or B<5>: 198 199 C:> script.pl <infile 200 C:> script.pl >outfile 201 C:> echo y | script.pl 202 C:> script.pl | more 203 204This is due to a Win32 bug which Perl has no control over. This bug 205is the major motivation for B<pl2bat> [which was originally written 206for DOS] being used on Win32 systems. 207 208Note also that B<5> works on a smaller range of combinations of Win32 209systems and command shells while B<4> requires that the user know 210that the script is a Perl script [because the ".pl" extension must 211be entered]. This makes it hard to standardize on either of these 212methods. 213 214=head2 DISADVANTAGES 215 216There are several potential traps you should be aware of when you 217use B<pl2bat>. 218 219The generated batch file is initially processed as a batch file each 220time it is run. This means that, to use it from within another batch 221file you should preceed it with C<call> or else the calling batch 222file will not run any commands after the script: 223 224 call script [args] 225 226Except under Windows NT, if you specify more than 9 arguments to 227the generated batch file then the 10th and subsequent arguments 228are silently ignored. 229 230Except when using F<CMD.EXE> under Windows NT, if F<perl.exe> is not 231in your B<PATH>, then trying to run the script will give you a generic 232"Command not found"-type of error message that will probably make you 233think that the script itself is not in your B<PATH>. When using 234F<CMD.EXE> under Windows NT, the generic error message is followed by 235"You do not have Perl in your PATH", to make this clearer. 236 237On most DOS-like operating systems, the only way to exit a batch file 238is to "fall off the end" of the file. B<pl2bat> implements this by 239doing C<goto :endofperl> and adding C<__END__> and C<:endofperl> as 240the last two lines of the generated batch file. This means: 241 242=over 243 244=item No line of your script should start with a colon. 245 246In particular, for this version of B<pl2bat>, C<:endofperl>, 247C<:WinNT>, and C<:script_failed_so_exit_with_non_zero_val> should not 248be used. 249 250=item Care must be taken when using C<__END__> and the C<DATA> file handle. 251 252One approach is: 253 254 . #!perl 255 . while( <DATA> ) { 256 . last if /^__END__$/; 257 . [...] 258 . } 259 . __END__ 260 . lines of data 261 . to be processed 262 . __END__ 263 . :endofperl 264 265The dots in the first column are only there to prevent F<cmd.exe> to interpret 266the C<:endofperl> line in this documentation. Otherwise F<pl2bat.bat> itself 267wouldn't work. See the previous item. :-) 268 269=item The batch file always "succeeds" 270 271The following commands illustrate the problem: 272 273 C:> echo exit(99); >fail.pl 274 C:> pl2bat fail.pl 275 C:> perl -e "print system('perl fail.pl')" 276 99 277 C:> perl -e "print system('fail.bat')" 278 0 279 280So F<fail.bat> always reports that it completed successfully. Actually, 281under Windows NT, we have: 282 283 C:> perl -e "print system('fail.bat')" 284 1 285 286So, for Windows NT, F<fail.bat> fails when the Perl script fails, but 287the return code is always C<1>, not the return code from the Perl script. 288 289=back 290 291=head2 FUNCTION 292 293By default, the ".pl" suffix will be stripped before adding a ".bat" suffix 294to the supplied file names. This can be controlled with the C<-s> option. 295 296The default behavior is to have the batch file compare the C<OS> 297environment variable against C<"Windows_NT">. If they match, it 298uses the C<%*> construct to refer to all the command line arguments 299that were given to it, so you'll need to make sure that works on your 300variant of the command shell. It is known to work in the F<CMD.EXE> shell 301under Windows NT. 4DOS/NT users will want to put a C<ParameterChar = *> 302line in their initialization file, or execute C<setdos /p*> in 303the shell startup file. 304 305On Windows95 and other platforms a nine-argument limit is imposed 306on command-line arguments given to the generated batch file, since 307they may not support C<%*> in batch files. 308 309These can be overridden using the C<-n> and C<-o> options or the 310deprecated C<-a> option. 311 312=head1 OPTIONS 313 314=over 8 315 316=item B<-n> I<ntargs> 317 318Arguments to invoke perl with in generated batch file when run from 319Windows NT (or Windows 98, probably). Defaults to S<'-x -S "%0" %*'>. 320 321=item B<-o> I<otherargs> 322 323Arguments to invoke perl with in generated batch file except when 324run from Windows NT (ie. when run from DOS, Windows 3.1, or Windows 95). 325Defaults to S<'-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9'>. 326 327=item B<-a> I<argstring> 328 329Arguments to invoke perl with in generated batch file. Specifying 330B<-a> prevents the batch file from checking the C<OS> environment 331variable to determine which operating system it is being run from. 332 333=item B<-s> I<stripsuffix> 334 335Strip a suffix string from file name before appending a ".bat" 336suffix. The suffix is not case-sensitive. It can be a regex if 337it begins with `/' (the trailing '/' is optional and a trailing 338C<$> is always assumed). Defaults to C</.plx?/>. 339 340=item B<-w> 341 342If no line matching C</^#!.*perl/> is found in the script, then such 343a line is inserted just after the new preamble. The exact line 344depends on C<$Config{startperl}> [see L<Config>]. With the B<-w> 345option, C<" -w"> is added after the value of C<$Config{startperl}>. 346If a line matching C</^#!.*perl/> already exists in the script, 347then it is not changed and the B<-w> option is ignored. 348 349=item B<-u> 350 351If the script appears to have already been processed by B<pl2bat>, 352then the script is skipped and not processed unless B<-u> was 353specified. If B<-u> is specified, the existing preamble is replaced. 354 355=item B<-h> 356 357Show command line usage. 358 359=back 360 361=head1 EXAMPLES 362 363 C:\> pl2bat foo.pl bar.PM 364 [..creates foo.bat, bar.PM.bat..] 365 366 C:\> pl2bat -s "/\.pl|\.pm/" foo.pl bar.PM 367 [..creates foo.bat, bar.bat..] 368 369 C:\> pl2bat < somefile > another.bat 370 371 C:\> pl2bat > another.bat 372 print scalar reverse "rekcah lrep rehtona tsuj\n"; 373 ^Z 374 [..another.bat is now a certified japh application..] 375 376 C:\> ren *.bat *.pl 377 C:\> pl2bat -u *.pl 378 [..updates the wrapping of some previously wrapped scripts..] 379 380 C:\> pl2bat -u -s .bat *.bat 381 [..same as previous example except more dangerous..] 382 383=head1 BUGS 384 385C<$0> will contain the full name, including the ".bat" suffix 386when the generated batch file runs. If you don't like this, 387see runperl.bat for an alternative way to invoke perl scripts. 388 389Default behavior is to invoke Perl with the B<-S> flag, so Perl will 390search the B<PATH> to find the script. This may have undesirable 391effects. 392 393On really old versions of Win32 Perl, you can't run the script 394via 395 396 C:> script.bat [args] 397 398and must use 399 400 C:> script [args] 401 402A loop should be used to build up the argument list when not on 403Windows NT so more than 9 arguments can be processed. 404 405See also L</Disadvantages>. 406 407=head1 SEE ALSO 408 409perl, perlwin32, runperl.bat 410 411=cut 412 413