Monday, June 9, 2008

Powershell Grep

If you're into Powershell, you may wish you could issue a grep command like you can in Linux. Guess what? You can!  Grep is a command that can search the contents of files for a regular expression.

In Powershell, we can do the same like so:
dir | select-string "my regex"

This command returns any matches (line by line) in any files in the current directory.  And if you want it to search through subdirectories as well:
dir -recurse | select-string "my regex"

If you have anything other than text files, this will dump a lot of nonsense and do a lot of really annoying beeping. To fix that you can tell it to only search files of a certain extension:
dir -recurse -include *.txt,*.cs | select-string "my regex"

This works great, but it's a lot of have to type, so I define a function in my $profile which I named grep.  You can check out my posh-prefs profile on bitbucket.

If all you wanted was to look at the names of the files, instead of the contents, you could:
dir | where { $_ -match "prefix*" }

Okay, I was just messing with you. You'd ACTUALLY do it like:
dir prefix*

Or recursively:
dir -recurse -include prefix*

Not only is this way shorter, it's actually more efficient because "the provider applies [it] when retrieving the objects, rather than having Windows PowerShell filter the objects after they are retrieved" (according to help dir -detailed).

6 comments:

  1. This is not correct. grep searches any input (which could be a file or could be a text string). The behavior of select-string is very different from grep. For example, ls | grep top would return a list of all lines from ls that contain the string "top". ls | select-string "top" returns all lines from all files containing the string "top", not the output of ls that contains that string.

    ReplyDelete
  2. Pingback from http://www.truewill.net/myblog/index.php/2009/04/20/grep_and_unicode

    ReplyDelete
  3. @Anonymous: Actually, it is correct, I'm getting the same behavior with Powershell that you would get from certain usages of Grep. The confusion stems from the fact that Grep is a high level tool, and therefore it encompasses a lot of functionality.

    Using Powershell you simply piece together a number of lower level tools to get exactly what you want.

    The equivalent to my second example which recursively searches all files in grep is grep -r 'my regex'.

    Note that you don't have to pipe anything to grep to search files, that is greps default behavior.

    For more, check out grep's documentation: http://www.gnu.org/software/grep/doc/grep_13.html#SEC13

    ReplyDelete
  4. Actually the help says that -filter is more efficient. Nice post, though; thanks!

    ReplyDelete
  5. One problem with select-string. It is *incredibly* slow. I'm searching inside a 300 mb file and returning certain lines if they match a specific pattern. Grep takes a few seconds, powershell at least 45 seconds. The price we pay for making everything an object...

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete