Finding files with a string

by rambog at 2012-11-28 12:22:29

I am trying to search through directories and locate files which match a particular string and list out the file name and what is contained on the line that matches the string. In this case, the string I am looking for begins with '<Name>. It ends with ‘</Name>’ and I am only interested in what is contained between these two tags.

Here is my command,
get-childitem ‘D:\Clients\ClientA\GPO Backup\BackupVersion1’|foreach-object{select-string -Path $.FullName -Pattern ‘<Name>’}

The erroneous output looks like,
Select-String : The file D:\Clients\ClientA\GPO Backup\BackupVersion1{F927988
6-0E48-4A53-A49D-F7BCCCEE1F89} can not be read: Access to the path ‘D:\Clients<br>ClientA\GPO Backup\BackupVersion1{F9279886-0E48-4A53-A49D-F7BCCCEE1F89}’ is d
enied.
At line:1 char:91
+ get-childitem ‘D:\Clients\ClientA\GPO Backup\BackupVersion1’|foreach-object{
select-string <<<< -Path $
.FullName -Pattern ‘<Name>’}
+ CategoryInfo : InvalidArgument: (:slight_smile: [Select-String], ArgumentEx
ception
+ FullyQualifiedErrorId : ProcessingFile,Microsoft.PowerShell.Commands.Sel
ectStringCommand

I have full access to that directory. The directory, BackupVersion1, has many sub-directories that have GUID names. Within each of these GUID directories, there is an XML file which contains the string I am looking for. What I would like to have is a hash table that has the GUID and the string between <Name> and </Name> within the XLM file. Any ideas on best approach and any idea why my script above is dying?
by DonJ at 2012-11-28 12:32:28
As a note, your syntax may be a little inefficient. You don’t need to get the files and then pipe them to ForEach; Select-String already knows how to read through a directory full of files. Just use…

Select-String -Path D:\Clients\ClientA\GPO Backup\BackupVersion1*

You do have to specify a file path, not just the folder, but you can use wildcards. But that won’t help you.

Now on to the actual question :). Select-String will barf an access denied if you give it a folder to read, as opposed to a file. That’s the issue, here. Going with your original syntax, I imagine you would want to add -recurse -file to Get-ChildItem. That’ll make it work through all the files, recursing subfolders, but only returning files and not folders. Select-String should have no problem with that. Note that -File is only supported with v3; if you’re using v2 you have to do something like…

Dir D:\Clients\ClientA\GPO Backup\BackupVersion1 | Where { -not $.PsIsContainer } | ForEach { blah blah blah }

Anyway, the deal is that you don’t want to be feeding folders to Select-String. Only files.
by DonJ at 2012-11-28 12:40:33
(I have to tell you, you may not enjoy doing what you’re after with Select-String. Doing this kind of searching, given the output you want, is awkward in a one-liner. I’d probably write a script).


$files = Dir -path D:\Clients\ClientA\GPO Backup\BackupVersion1 -include *.xml -recurse | Where { -not $
.PSIsContainer }
$out = @{}
foreach ($file in $files) {
[xml]$xml = Get-Content $file.fullname
$results = $xml | select-xml -xpath "//Name" | foreach { $_.node.innerxml }
foreach ($result in $results) {
$out.add($file.fullname,$result)
}
}
$out


Something like that should get you the values of all the Name nodes in every XML file. Note that XML is case-sensitive, so if it’s <name> put "//name" for the XPath.