Powershell to replace text in multiple files stored in many folders

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 $_) }

$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
}

$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
}