NAME
Win32::CommandLine - Retrieve and reparse the Win32 command line
VERSION
This document describes Win32::CommandLine
($Version: 0.4.2.605 $).
SYNOPSIS
@ARGV = Win32::CommandLine::argv() if eval { require Win32::CommandLine; };
_or_
use Win32::CommandLine qw( command_line );
my $commandline = command_line();
...
DESCRIPTION
This module is used to reparse the Win32 command line, automating better quoting and globbing of the command line. Globbing is full bash POSIX compatible globbing, including subshell expansions. With the use of the companion script (xx.bat) and doskey for macro aliasing, you can add full-fledged bash compatible string quoting/expansion and file globbing to any Win32 command.
This module is compatible with both cmd.exe and 4nt/tcc/tcmd shells, adding better parsing and bash glob expansion to any external command, by using the included xx
batch script.
CMD.EXE
doskey type=call xx type $*
type [a-c]*.pl
doskey perl=call xx perl $*
perl -e 'print "test"' [o/w FAILS without commandline reinterpretation]
4NT/TCC/TCMD
alias type=call xx type
type [a-c]*.pl
alias perl=call xx perl
perl -e 'print "test"' [o/w FAILS without commandline reinterpretation]
Note that bash compatible character expansion and globbing is available, including meta-notations such as a[bc]*
or foo.{bat,pl,exe,o}
.
Command line string/character expansion
'...' => literal (no escapes and no globbing within quotes)
"..." => literal (no escapes and no globbing within quotes)
$'...' => string including all ANSI C string escapes (\a, \b, \e, \f, \n, \r, \t, \v, \\, \', \n{1,3}, \xh{1,2}, \cx; all other escaped characters: \<x> =>\<x>); no globbing within quotes
$"..." => literal (no escapes and no globbing within quotes) [same as "..."]
$( ... ) => subshell expansion [subshell commandline is _not_ expanded]
$("...") => subshell expansion (quotes removed) [subshell commandline is _not_ expanded]
Command line globbing
\ Quote the next metacharacter
[] Character class
{} Multiple pattern
* Match any string of characters
? Match any single character
~ Expand to current user home directory
~<name> Expands to user <name> home directory for any defined user [ ONLY if {Win32, Win32::Security::SID, Win32::TieRegistry} are installed; o/w no expansion => pull off any leading non-quoted ~[name] (~ followed by word characters) => replace with home dir of [name] if exists, otherwise replace the characters)
~<text> Expands to value of environment variable "~<text>" (if defined) [OVERRIDES ~<name> expansion]
INSTALLATION
To install this module, run the following commands:
perl Build.PL
./Build
./Build test
./Build install
Or, if you're on a platform (like DOS or Windows) that doesn't require the "./" notation, you can do this:
perl Build.PL
Build
Build test
Build install
Alternatively, the standard make idiom is also available (though deprecated):
perl Makefile.PL
make
make test
make install
(On Windows platforms you should use nmake
instead.)
As Makefile.PL is just a pass-through script, Module::Build is still ultimately required for installation. Makefile.PL will offer to download and install Module::Build if it is missing from your current installation.
PPM installation bundles should also be available in the standard PPM repositories (i.e. ActiveState, trouchelle.com [http://trouchelle.com/ppm/package.xml]).
Note: On ActivePerl installations, './Build install' will do a full installation using ppm
(see ppm).
INTERFACE
SUBROUTINES/METHODS
command_line( )
command_line()
returns the full Win32 command line as a string.
argv( )
argv()
returns the reparsed command line as an array.
parse( $ )
parse( $ )
takes a string argument and returns the parsed argument string as an array.
RATIONALE
This began as a simple need to work-around the less-than-stellar COMMAND.COM
/CMD.EXE
command line parser, just to accomplish more `correct` quotation interpretation. It then grew into a small odyssey: learning XS and how to create a perl module, learning the perl build process and creating a customized build script/environment, researching tools and developing methods for revision control and versioning, learning and creating perl testing processes, and finally learning about PAUSE and perl publishing practices. And, somewhere in the middle, adding some of the bash
shell magic to the CMD shell (and, additionally, making it compatible with the excellent [and free] TCC-LE shell from JPSoft [find it at http://jpsoft.com/]).
Some initial attempts were made using Win32::API
and Inline::C
. For example (Win32::API
attempt [caused GPFs]):
@rem = '--*-Perl-*--
@echo off
if "%OS%" == "Windows_NT" goto WinNT
perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
perl -x -S %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
if %errorlevel% == 9009 echo You do not have Perl in your PATH.
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperl
@rem ';
#!/usr/bin/perl -w
#line 15
#
use Win32::API;
#
Win32::API->Import("kernel32", "LPTSTR GetCommandLine()");
my $string = pack("Z*", GetCommandLine());
#
print "string[".length($string)."] = '$string'\n";
# ------ padding --------------------------------------------------------------------------------------
__END__
:endofperl
Unfortunately, Win32::API
and Inline::C
were shown to be too fragile at the time (in 2007). Win32::API
caused occasional (but reproducible) GPFs, and Inline::C
is very brittle on Win32 systems (not compensating for paths with embedded strings). [ See http://www.perlmonks.org/?node_id=625182 for a more full explanation of the problem and initial attempts at a solution. ]
So, an initial XS solution was implemented. And from that point, the lure of bash
-like command line parsing led inexorably to the full implementation. The parsing logic is unfortunately still complex, but seems to be holding up under testing.
IMPLEMENTATION and INTERNALS
wrap_GetCommandLine() :: [XS] Use C and Win32 API to get the command line.
DIAGNOSTICS
Pending documentation...
CONFIGURATION AND ENVIRONMENT
Win32::CommandLine
requires no configuration files or environment variables.
DEPENDENCIES
Win32::CommandLine
requires Carp::Assert
for internal error checking and warnings.
The optional modules Win32
, Win32::API
, Win32::Security::SID
, and Win32::TieRegistry
are recommended to allow full glob tilde expansions for user home directories (eg, ~administrator
expands to C:\Users\Administrator
). Expansion of the single tilde (~
) has a backup implementation based on %ENV variables, and therefore will still work even without the optional modules.
INCOMPATIBILITIES
None reported.
BUGS AND LIMITATIONS
Please report any bugs or feature requests to bug-Win32-CommandLine@rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Win32-CommandLine. The developers will be notified, and you'll automatically be notified of progress on your bug as any changes are made.
Operational Notes
IMPORTANT NOTE: Special shell characters (shell redirection [ '<', '>' ] and continuation '&') must be **DOUBLE-quoted** to escape shell interpretation (eg, "...
...">). The CMD shell does initial parsing and redirection/continuation (stripping away everything after I/O redirection and continuation characters) before any process can get a look at the command line. So, the special shell characters can only be hidden from shell interpretation by DOUBLE-quoting them.
%<x
> is also replaced by the corresponding %ENV variable by the CMD shell before handing the command line off to the OS. So, %%
must be used to place single %'s in the command line, eg: perl -e "use Win32::CommandLine; %%x = Win32::CommandLine::_home_paths(); for (sort keys %%x) { print qq{$_ =
$x{$_}\n}; }">.
Brackets ('{' and '}') and braces ('[' and ']') must be quoted to be matched literally. This may be a gotcha for some users, although if the filename has internal spaces, the standard Win32 shell (cmd.exe) will automatically surround the entire path with spaces (which corrects the issue).
Some programs may expect their arguments to maintain their surrounding quotes, but argv() parsing only quotes arguments which require it for shell parsing (i.e., those containing spaces, special characters, etc).
Be careful with backslashed quotes within quoted strings. Note that "...\" is an unbalanced string containing a double quote. Place the backslash outside of the quotation ("...\"") or use a double backslash ("...\\"
) to include it in the parsed token. However, backslashes ONLY need to be doubled when placed prior to a quotation mark ("...\..."
works as expected).
4NT/TCC/TCMD NOTE: The shell interprets and removes backquote characters before executing the command. You must quote backquote characters with **double-quotes** to pass them into the command line (eg, {perl -e "print `dir`"} NOT {perl -e 'print `dir`'} ... the single quotes do not protect the backquotes which are removed leaving just {dir}).
Bugs
No bugs have been reported.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Win32::CommandLine
You can also look for information at:
* AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/Win32-CommandLine
* CPAN Ratings
http://cpanratings.perl.org/dist/Win32-CommandLine
* RT: CPAN's request tracker (aka buglist)
http://rt.cpan.org/Public/Dist/Display.html?Name=Win32-CommandLine
* Search CPAN
http://kobesearch.cpan.org/dist/Win32-CommandLine
_or_
http://search.cpan.org/dist/Win32-CommandLine
* CPANTS: CPAN Testing Service
[kwalitee] http://cpants.perl.org/dist/kwalitee/Win32-CommandLine
[used by] http://cpants.perl.org/dist/used_by/Win32-CommandLine
* CPANTESTERS: Test results
http://www.cpantesters.org/show/Win32-CommandLine.html
ACKNOWLEDGEMENTS
AUTHOR
Roy Ivy III <rivy[at]cpan[dot]org>
LICENSE AND COPYRIGHT
Copyright (c) 2007-2009, Roy Ivy III <rivy[at]cpan[dot]org>. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.
DISCLAIMER OF WARRANTY
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE ''AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.