tsunami

log in
history

PowerShell: Execute-Cmd

Luke Breuer
2008-12-20 11:08 UTC

Introduction
Powershell's object-oriented nature has a bad side effect when it comes to the Unix toolset's approach of processing line-by-line: it is slow. It just takes enough time to wrap output in System.String and unwrap input when piping to executables that processing millions of lines takes an appreciable amount of time. It is much faster to do such things with cmd.exe. Unfortunately, all the string escaping and whatnot to use cmd /c "unzip -p what.zip | cut -f 1,2 -d `"|`"" is annoying. There is a better approach.
Code Blocks
Something that may not be well-known is that code blocks are enclosed by {} in PowerShell and can be converted .ToString() quite easily. This provides for a very nice hack.
The Code
This is ready for insertion into one's PS profile (notepad "$profile"):
function GLOBAL:Execute-Cmd($codeBlock)
{
    if ($codeBlock -eq $null)
    {
        throw "codeBlock cannot be null"
    }
    
    cmd /c $codeBlock.ToString()
}

set-alias cmdc Execute-Cmd
After you save that, you can .$profile to recompile your profile so that the current PS instance has the most up-to-date version.
Usage
(This assumes installation of some GNU Win32 executables.)
cmdc { unzip -p what.zip | cut -f 1,2 -d "|" | head -n 100 | sort | uniq}
Caveats
parsing -d"|"
The following will not parse as intended, due to how PS tokenizes commands:
cmdc { cut -d"|" }
(Notice that there is no space between the -d and the "|".)
proper string escaping
There could be other parsing/tokenizing issues as discussed above that I have yet to uncover. Please contact me (see the bottom of this page) if you find other caveats or improvements.
no string interpolation
If you embed a $variable in the {...} passed to Execute-Cmd, it will not be expanded.