Powershell - listing folders in mulitple places an

2019-09-06 00:41发布

问题:

I'm trying to set up a script designed to change a bit over 100 placeholders in probably some 50 files. In general I got a list of possible placeholders, and their values. I got some applications that have exe.config files as well as ini files. These applications are stored in c:\programfiles(x86)\ and in d:\In general I managed to make it work with one path, but not with two. I could easily write the code to replace twice, but that leaves me with a lot of messy code and would be harder for others to read.

ls c:\programfiles(x86) -Recurse | where-object {$_.Extension -eq ".config" -or $_.Extension -eq ".ini"} | %{(gc $PSPath) | %{
$_ -replace "abc", "qwe" `
-replace "lkj", "hgs" `
-replace "hfd", "fgd"
} | sc $_PSPath; Write-Host "Processed: " + $_.Fullname}

I've tried to include 2 paths by putting $a = path1, $b = path2, c$ = $a + $b and that seems to work as far as getting the ls command to run in two different places. however, it does not seem to store the path the files are in, and so it will try to replace the filenames it has found in the folder you are currently running the script from. And thus, even if I might be in one of the places where the files is supposed to be, it's not in the other ...

So .. Any idea how I can get Powershell to list files in 2 different places and replace the same variables in both places without haveing to have the code twice ? I thought about putting the code I would have to use twice into a variable, calling it when I needed to instead of writing it again, but it seemed to resolve the code before using it, and that didn't exactly give me results since the data comes from the first part.

回答1:

If you got a cool pipeline, then every problem looks like ... uhm ... fluids? objects? I have no clue. But anyway, just add another layer (and fix a few problems along the way):

$places = 'C:\Program Files (x86)', 'D:\some other location'
$places |
  Get-ChildItem -Recurse -Include *.ini,*.config |
  ForEach-Object {
    (Get-Content $_) -replace 'abc', 'qwe' `
                     -replace 'lkj', 'hgs' `
                     -replace 'hfd', 'fgd' |
      Set-Content $_
    'Processed: {0}' -f $_.FullName
  }

Notable changes:

  • Just iterate over the list of folders to crawl as the first step.
  • Doing the filtering directly in Get-ChildItem makes it faster and saves the Where-Object.
  • -replace can be applied directly to an array, no need for another ForEach-Object there.

If the number of replacements is large you may consider using a hashtable to store them so that you don't have twenty lines of -replace 'foo', 'bar'.