How can I escape an arbitrary string for use as a command line argument in Windows?

Here is an msdn blogpost showing how. It however assumes that every command line program internally uses CommandLineToArgvW to parse it's command line (not a shabby assumption, since it's part of the Shell32 library).

Original link (may not work): http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx

Web archive link: https://web.archive.org/web/20190109172835/https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/


To escape a command line argument, use the following:

sub escapeArg {
  my $arg = shift;

  # Sequence of backslashes followed by a double quote:
  # double up all the backslashes and escape the double quote
  $arg =~ s/(\\*)"/$1$1\\"/g;

  # Sequence of backslashes followed by the end of the arg,
  # which will become a double quote later:
  # double up all the backslashes
  $arg =~ s/(\\*)$/$1$1/;

  # All other backslashes do not need modifying

  # Double-quote the whole thing
  $arg = "\"".$arg."\"";

  # Escape shell metacharacters
  $arg =~ s/([()%!^"<>&|;, ])/\^$1/g;

  return $arg;
}

To escape the actual command line command, for example when invoking a command with a ridiculous name such as ()!&%PATH%^;, .exe (which is perfectly legal), use the following:

sub escapeCmd {
  my $arg = shift;

  # Escape shell metacharacters
  $arg =~ s/([()%!^"<>&|;, ])/\^$1/g;
  return $arg;
}

Note that using escapeArg() for the command will not work.

Sources:

  • http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
  • http://support.microsoft.com/kb/103368

Tags:

Windows

Shell

Cmd