Brad Wilson - The .NET Guy

Technologist. Agile Evangelist. Poker Player. Amateur Neologist. Metalhead.

My Links

Post Categories

Article Categories

Archives

Blog Stats

Stuff

Brian's Find Dilemma

Brian has been searching for a PowerShell replacement to a Unix command and came up with this:

get-childitem -include foo.* -recurse | where-object { get-content $_ | select-string find_me }

Here it is, shortened for interactivity:

[1] » dir -r -i *.ps1 | ?{ gc $_ | select-string "get-childitem" }

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         6/11/2006   6:10 PM         46 find-files.ps1
-a---         6/12/2006   5:39 PM        411 find-string.ps1
-a---         10/9/2005  11:22 AM        149 get-linecount.ps1
-a---         6/17/2006   1:08 PM       1173 prep-mp3s.ps1
-a---         9/27/2006   9:31 AM        668 show-signers.ps1
-a---         5/30/2006  11:49 AM       2449 TabExpansion.ps1

That's not too bad, but if you leave off the where clause, it shows you line #s and text:

[2] » dir -r -i *.ps1 | select-string "get-childitem"

find-files.ps1:1:get-childitem -force -recurse -include $ar gs
find-string.ps1:3:get-childitem -recurse -include $args[0] | [...]
get-linecount.ps1:3:(get-childitem -i $match -r | grep $re | [...] prep-mp3s.ps1:10:get-childitem -r -i *.mp3 | foreach-object { show-signers.ps1:1:$inputs = $(get-childitem) TabExpansion.ps1:40:foreach ($v in Get-Childitem ('variable:'[...]

That's the right information, in a format I don't like. Maybe that's why Brian does it his way.

This is a script that I ended up with a few months ago (the bulk of which came from IanG):

get-childitem -recurse -include $args[0] |
    select-string $args[1] |
    group-object Path |
    select-object @{Expression={$_.Name.Substring((get-location).Path.Length + 1)}; Name="Filename" }, @{Expression={$_.Group | %{ $_.LineNumber}}; Name="Line Numbers"} |
    format-table -Autosize

Which works like this:

[3] » find-string *.ps1 get-childitem

Filename                               Line Numbers
--------                               ------------
find-files.ps1                                    1
find-string.ps1                                   3
get-linecount.ps1                                 3
prep-mp3s.ps1                                    10
show-signers.ps1                                  1
TabExpansion.ps1                                 40

If something occurs multiple times, the line numbers get grouped up:

[4] » find-string *.ps1 set-content

Filename                               Line Numbers
--------                               ------------
append-path.ps1                        9
Microsoft.PowerShell_profile.ps1       {30, 34, 62, 63}
prepend-path.ps1                       9

Note: While I use aliases interactively (like "dir" instead of "get-childitem"), I always use full-names in scripts, because you don't know when people will override aliases. Using full switch names isn't a bad practice, either, since your unambiguous short name for a switch might not be so unambiguous in the future (and it makes the scripts a bit easier to read, too).

posted on Thursday, March 22, 2007 4:36 PM