FINDSTR Equivalent in PowerShell

I ran across this blog post by Ian Griffiths called Learning PowerShell: FINDSTR Equivalent which motivated me to come up with my own flavor of this sort of utility.  The great thing about PowerShell is that you can take these scripts and customize them to suit your tastes.  Here is what I came up with.  Just put the following in  a script called FindString.ps1:
 
param([string]$Pattern,
      [string[]]$Path,
      [switch]$Recurse,
      [switch]$Verbose,
      [switch]$SimpleMatch)
     
if ($Pattern -eq "" -or $Path -eq "") {
    "Usage: FindString <pattern> <path> [-Recurse] [-Verbose] [-SimpleMatch]"
    ""
    "Pattern:     Search string. Single quote to avoid shell interpretation"
    "Path:        File(s) to search.  Can be wilcard expression"
    "Recurse:     Searches sub directories if specified"
    "Verbose:     Prints first 74 characters of matched line"
    "SimpleMatch: Pattern is not interpreted as a regular expression"
    ""
    "Example usage:"
    "PS> FindString typedef *.h -verbose"
    "PS> FindString ‘def.*BOOL’ win*.h -recurse"
    "PS> FindString ‘this.Clear’ foo.cs, bar.cs -simplematch"
    "PS> FindString ‘(?<areacode>\({\d}3\)’ *.cs -r -v -s"
    ""
    exit
}
if ($verbose) {
    Get-ChildItem . -include $path -recurse:$Recurse  |
        Select-String $Pattern -SimpleMatch:$SimpleMatch |
        Format-Table -GroupBy Filename `
                     @{e={$_.LineNumber};l="Line#";w=5},
                     @{e={$_.Line.Trim()};l="Line"}
}
else {
    Get-ChildItem . -include $path -recurse:$Recurse |
        Select-String $Pattern -SimpleMatch:$SimpleMatch |
        Group-Object Filename |
        Format-Table  @{e={$_.Name};l="Filename";w=50},
                      @{e={$_.Group|%{$_.LineNumber}};l="Lines";w=30}
}
 
A couple of things to note about this script.  First, in PowerShell you normally specify a switch parameter without any value like so:
 
PSH> Get-ChildItem . -Recurse
 
Switch parameters are essentially just booleans where their presence indicates $true and their absence results in a default value of $false.  However you can also specify the bool value for a switch like this:
 
PSH> Get-ChildItem . -Recurse:$true
 
You may be wondering why the heck this would be useful.  Take a look at how I pass the "Recurse" and "SimpleMatch" switch parameters to the Get-ChildItem and Select-String cmdlets respectively.  If PowerShell didn’t allow you to specify the value for a switch parameter then the script logic would be a good bit uglier.
 
The other thing to note is that the Path parameter is declared as type string[].  This was the only way I could get a single expression involving Get-ChildItem to work with a path spec of "*.h" as well as "foo.cs, bar.cs". 
Advertisements
This entry was posted in PowerShell. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s