Find string, exclude folder; list results

Welcome Forums General PowerShell Q&A Find string, exclude folder; list results

Viewing 6 reply threads
  • Author
    Posts
    • #184191
      Participant
      Topics: 120
      Replies: 258
      Points: 229
      Rank: Participant

      Hello,

      I have this working script:

      $AllDCs = Get-Content .\AllDCs.txt
      foreach($DC in $AllDCs){
      Get-ChildItem -Path E:\, C:\ -Include *.ps1, *.xml, *.bat -Recurse -Name -Exclude E:\Scripts\IGNORE | Select-String -Pattern SomeFileName
      }

      ..but my output doesn't tell me which DC the result(s) was found. How can I modify the script to show that, please?

    • #184197
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      That's because the DCs are just references you're using FOR the foreach loop, and not actually IN the foreach loop.

      You'll need to assign the output of Get-ChildItem to a variable, then create a [pscustomobject] to include the DC as a property.

      This example will output the DC name but the files output is probably not what you want:

      foreach ($DC in $AllDCs) {
      
          $files = Get-ChildItem ...
      
          [pscustomobject]@{
              DC = $DC
              Files = $files
          }
      }

      To show DC names for each file, you'll need to loop through all files as well, and then create a `[pscustomobject]`:

      foreach ($DC in $AllDCs) {
      
          $files = Get-ChildItem ...
      
          foreach ($file in $files) {
      
              [pscustomobject]@{
                 DC = $DC
                 FilePath = $file.FullName
                 # other properties
              }
          }
      }
      • #184248
        Participant
        Topics: 120
        Replies: 258
        Points: 229
        Rank: Participant

        Aaron,

        I tried your suggestion:

        $AllDCs = Get-Content .\AllDCs.txt
        
         foreach ($DC in $DCs) {
        
            $files = Get-ChildItem -Path E:\, C:\ -Include *.ps1, *.xml, *.bat -Recurse -Name -Exclude E:\Scripts\IGNORE | Select-String -Pattern SomeFileName1
        
            foreach ($file in $files) {
        
                [pscustomobject]@{
                   DC = $DC
                   FilePath = $file.FullName
                   # other properties
                }
            }
        }

        ..but no output and no error.

      • #184269
        Participant
        Topics: 10
        Replies: 117
        Points: 457
        Helping Hand
        Rank: Contributor

        Sorry Jeff, a little quick on the draw. Instead of foreach ($DC in $DCs), it should have been foreach ($DC in $AllDCs) as per your code. I've updated that post. Give it a shot.

      • #184350
        Participant
        Topics: 120
        Replies: 258
        Points: 229
        Rank: Participant

        Aaron,

        It runs without error and simply outputs the Name of the DC and no values under Filepath. I tested it with a keyword (TestUser@myCompany.com) for which I know exists in a .ps1 file but the Get-ChildItem isn't finding it.

        Here's my revised script:

         $AllDCs = Get-Content .\AllDCs.txt
         foreach ($DC in $AllDCs) {
        
            $files = Get-ChildItem -Path E:\ -Include *.ps1, *.xml, *.bat -Recurse | Select-String -Pattern TestUser@myCompany.com
        
            foreach ($file in $files) {
        
                [pscustomobject]@{
                   DC = $DC
                   FilePath = $file.FullName
                }
            }
        }
      • #184431
        Participant
        Topics: 10
        Replies: 117
        Points: 457
        Helping Hand
        Rank: Contributor

        Thanks Jeff, I realized more needed to be addressed here and I spaced on the pscustomobject.

        If you use the -Include parameter, you do need an asterisk (*) at the end of  -Path E:\, otherwise you'll get nothing back. So, here is what should work:

        foreach ($DC in $AllDCs) {
        
            $files = Get-ChildItem -Path E:\* -Include *.ps1, *.xml, *.bat -Recurse | Select-String -Pattern somePattern
        
            foreach ($file in $files) {
        
                [pscustomobject]@{
                    DC       = $DC
                    FilePath = $file.Path
                }
            }
        }

        Now, keep in mind that though this code would work for what it is, the reference to DCs is irrelevant. The code is just looping through DCs in a text file (assumingly Domain Controller names), and for each one found in the file, it outputs the DC name with a file path found against some pattern you specify.

        If 150 files are found matching the pattern, those results will output for each DC in the text file. This means if you have 10 DCs in the text file, the output will render 1500 results, almost all of which are redundant.

        Are you intending to run this against domain controller found in the .txt file? What is your plan for this script?

      • #184437
        Participant
        Topics: 120
        Replies: 258
        Points: 229
        Rank: Participant

        ah, I had no idea about the * in the -Include, so thank you.

        They are indeed DC's and I'm looking for that one script (either .ps1 or .xml) that has a username, generating lockouts etc. So wouldn't expect it to be on all DCs but rather, one.

    • #184200
      Participant
      Topics: 10
      Replies: 117
      Points: 457
      Helping Hand
      Rank: Contributor

      I forgot to throw this in:

      If you want to group by DC, you can pipe the top foreach to Format-Table which will output things nicely in the console (if you don't need a CSV):

      $results = foreach ($DC in $DCs) { ... }
      
      $results | Format-Table -GroupBy DC
    • #184203
      Senior Moderator
      Topics: 8
      Replies: 1141
      Points: 3,928
      Helping Hand
      Rank: Community Hero

      What is DC here ? Where are you using $DC here ?

    • #184449
      Participant
      Topics: 4
      Replies: 84
      Points: 368
      Helping Hand
      Rank: Contributor

      There is a glaring issue in the code as posted. You are not initiating a remote session to the DCs nor are you defining a UNC with the -LiteralPath parameter. As it appears now, its going to list the DCs and invoke GCI against your local E:\ for reach DC in AllDCs.

       

      
      Get-ChildItem -LiteralPath "\\$dc\E$\" -Include *.ps1, *.xml, *.bat -Recurse | Select-String -Pattern TestUser@myCompany.com
      
      
      • #184470
        Participant
        Topics: 120
        Replies: 258
        Points: 229
        Rank: Participant

        You are not initiating a remote session to the DCs nor are you defining a UNC

        I think I was ok with that. Just run it locally.

        You will want to escape that with a "\" example "TestUser@mycompany\.com"

        I will try that too thanks. I'm getting the results at least now, associated with the DC and FilePath output. The "*" helped.

      • #184500
        Participant
        Topics: 4
        Replies: 84
        Points: 368
        Helping Hand
        Rank: Contributor

        "I think I was ok with that. Just run it locally."

        I admit I am a little confused by your response, forgive me. If you intend to run the script locally, then what is the ForEach loop doing?

    • #184452
      Participant
      Topics: 4
      Replies: 84
      Points: 368
      Helping Hand
      Rank: Contributor

      Another note, Select-String is using Regex, and "." in Regex is wildcard. You will want to escape that with a "\" example "TestUser@mycompany\.com"

       

    • #184574
      Participant
      Topics: 4
      Replies: 99
      Points: 210
      Helping Hand
      Rank: Participant

      I don't quite understand what the goal is just by looking the "working" script in the first post.

      but, could this be the thing you are trying to achieve

      
      $computers = get-content "c:\temp\AllDCs.txt"
      
      $scriptBlock = {
      $paths = "C:\temp","C:\users"
      $excludePath = "C:\users\*\PS\functions"
      
      Get-ChildItem -Path $paths -Include *.ps1, *.xml, *.bat -Recurse -ErrorAction SilentlyContinue |
      where {$_.DirectoryName -notlike $excludePath} |
      Select-String computer |
      Group-Object path |
      select @{N='host';E={$env:COMPUTERNAME}}, @{N='FullName';E={$_.name}}
      
      }
      
      invoke-command -ComputerName $computers -ScriptBlock $scriptBlock
      
      
      • #184643
        Participant
        Topics: 120
        Replies: 258
        Points: 229
        Rank: Participant

        This worked very well. I just:

        ~added "*" to the end of those paths (i.e. "C:\users\*")
        ~ added -ErrorAction SilentlyContinue at the end of the Invoke-command, to ignore the access denied warnings to some folders

        I also learned a lot from this, so thank you Aapeli.

Viewing 6 reply threads
  • You must be logged in to reply to this topic.