Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Alias (5735)

Alias
  (email not shown publicly)
http://ali.as/

Journal of Alias (5735)

Wednesday July 30, 2008
06:22 AM

As easy as FOR %%i IN ( %0 ) DO %%~di%%~piperl -x -S %0 %*

[ #37055 ]

Seriously, the things I do for you people.

With the Portable alpha, and feedback starting to roll in, the most obviously blocker for Perl on a Stick is that the batch files produced by pl2bat don't work when Perl isn't in PATH, which for the portable situation is a given.

The trouble with batch programming is that it's such a dead language at this point, it's hard to even find good information about it.

So in Portland, I undertook an expedition to the glorious fantabulous Powell's Books, in the hope that if anyone could find me something, they could.

Alas, the only remain batch file programming book in the United States was stuck in their warehouse in Chicago! :(

Fortunately, Powell's expert Michael Schwern came to my rescue and after some scrounging in the second hand books sections, emerged with just what I needed.

Aside from being extremely old, it also happens to be about the most embarrassing technical book I've ever owned. Pulling it out at the coffee shop in front of an assembled gaggle of Perl/OSCON geeks resulted in a loud chorus of laughter...

http://www.flickr.com/photos/xwrn/2702817504/

And so between this book, some built in Windows help information, and some online tutorials, I've managed to piece together a fix to pl2bat to make the batch script look for and use the perl executable in the same directory as the .bat file, rather than using the PATH version.

The specific line is:

FOR %%i IN ( %0 ) DO %%~di%%~piperl -x -S %0 %*

In a way, I'm quite lucky that it turned out so easy, given how utterly dysfunctional Windows batch is as a "language". By comparison, shell script is elegant and well structured.

The key problem here is that batch doesn't have any string manipulation functions at all, nor does it have much of a file system interface either.

It does (sort of) support variables, which is the "%i" in the above. Except that it's only %i if you use a variable on the command line. Inside a batch script you have to use %%i instead. Don't ask me why, I've never seen any explanation. It just is.

The "perl -x -S" bit is straight forward by comparison...

%0 is the equivalent of $0, and %* is the equivalent of @ARGV.

The tricky bit here is that there's literally no way to turn a string like C:\strawberry\perl\bin\foo.bat into C:\strawberry\perl\bin\perl.exe, so you can call the correct Perl instance.

So instead, we need to badly abuse some evil functionality built into the FOR command/loop.

The FOR command has a bunch of wildly diverse, and utterly insane, ways of working.

But the interesting one is when you use it to iterate over files, like so:

FOR %%variable IN ( file1.txt file2.txt ) DO something

If, and ONLY if, FOR is used to iterate over a list of files, and it knows they are files, then some magic %%variable stuff comes into existance.

These looks like %%~(letter)variable, and let you access different bits or variations of the file name.

The two useful ones in this case is %%~dvariable, which gives us the drive letter for the file in the form "C:", and %%~pvariable which gives the path in the form "\strawberry\perl\bin\".

And thus, by doing a completely useless single value for loop FOR %%i IN ( %0 ) DO we can cause the magic variables we need to come into existance, from which we can just do a simple string concatination (which needs no syntax, because it's just implied) and add perl.exe to the end, which gets us all the way to something that is rediculous, but works.

Of course, this only works post-installation, and wouldn't be usable at all if you called it in the modules blib at build time...

Making THAT works gets even weirder, and will most likely require more thought.

But it does look like I'll have batch stuff working properly by the time YAPC::EU rolls around, making the YAPC::EU "Perl on a Perl on a Stick Stick" much more functional than the American version :)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Because it's actually as simple as:

    "%~dp0perl.exe" -x -S "%~f0" %*

    The quotations and "%~f0" are needed in case batch file is in a directory with whitespaces.

  • I'm "stuck" with just a MacBook in Europe right now, so I can't easily test this, but when i was playing around with this last time I noticed that there were several bugs in cmd.exe that prevented the %~ expansion from working correctly. Things like invoking the batch file and explicitly specifying the .bat extension and/or putting quotes around the command name.

    You can find my earlier attempt here: http://groups.google.com/group/perl.perl5.porters/msg/b1880b658b5ab73f [google.com]

    It worked for all the test cases

  • Batch certainly sucks, it even has two(!) incomplete sets of escaping rules.

    So instead of that complete and utter mess, why not use Windows Scripting Host [wikipedia.org]? That sounds a lot easier.

    • A very long ago, when I needed to automate things and didn't know .net/perl/python I was using WSH (via its javascript), and I must say it sucks even more. Especially since windowed/console mode is a global setting, plus it had some funny glitches in child processes execution. So, batch files are much better.