Reputation: 6833
I want to replace a text in multiple files and folders. The folder name changes, but the filename is always config.xml.
$fileName = Get-ChildItem "C:\config\app*\config.xml" -Recurse
(Get-Content $fileName) -replace 'this', 'that' | Set-Content $fileName
When I run the above script it works, but it writes the whole text in config.xml about 20 times. What's wrong?
Upvotes: 18
Views: 32142
Reputation: 294
I got list of files to replace text this way.
$filenames = Get-ChildItem|Select-String -Pattern ""|select Filename
This gets 12 files.
To replace this text in all files
foreach ($filename in $filesnames){ (Get-Content $filename.Filename) -replace "", ""|Set-Content $filename.Filename }
Don't forget last part for Filename. $filename.Filename
Upvotes: 0
Reputation: 3639
In general, you should use the pipeline and combine the ForEach-Object
and/or Where-Object
CmdLets.
In your case, this would like like something more akin to:
Get-ChildItem "C:\config\app*\config.xml" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace 'this', 'that' | Set-Content $_
}
Which can be shortened somewhat to:
dir "C:\config\app*\config.xml" -recurse |% { (gc $_) -replace 'this', 'that' | (sc $_) }
Upvotes: 12
Reputation: 68243
$filename is an array of filenames, and it's trying to do them all at once. Try doing them one at a time:
$fileNames = Get-ChildItem "C:\config\app*\config.xml" -Recurse |
select -expand fullname
foreach ($filename in $filenames)
{
( Get-Content $fileName) -replace 'this', 'that' | Set-Content $fileName
}
Upvotes: 6
Reputation: 26120
$filename is a collection of System.IO.FileInfo objects
.
You have to loop to get the content for each file :
this should do what you want :
$filename | %{
(gc $_) -replace "THIS","THAT" |Set-Content $_.fullname
}
Upvotes: 18