Replace multiple strings in a file using powershell - powershell

I am using following coe to replace the string
$folders=Get-ChildItem -Path "C:\temp\Database Scripts"
foreach($folder in $folders)
{
Write-Host $folder
$spath=[string]::Concat("C:\temp\Database Scripts\", $folder)
$subfolders=Get-ChildItem $spath
foreach($subfolder in $subfolders )
{
if($subfolder -match "Running Scripts")
{
$subfolerpath=[string]::Concat($spath,"\",$subfolder,"\*")
$files =get-childitem -Path $subfolerpath -include "AVEVAScripts*"
if($files -ne $null)
{
foreach( $file in $files)
{
Write-Host $file;
(Get-Content $file) | ForEach-Object {$_ -replace "DATABASE_USER","fhghjgj" `
-replace "DATABASE_PASSWORD", "DFGHFHJGJH" } |Set-Content $file
}
}
}
}
}
But ending up with following error.
Set-Content : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
Please help :)

Remove the $x in the end of Set-Content. $x is never declared.
Also, you could simplify it a lot. Ex:
Get-ChildItem -Filter "Running Scripts" -Path "C:\temp\Database Scripts" -Recurse | ForEach-Object {
Get-ChildItem -Path $_.FullName -Filter "AVEVAScripts*" -Recurse | ForEach-Object {
(Get-Content $_.FullName) | ForEach-Object {
$_ -replace "DATABASE_USER","fhghjgj" -replace "DATABASE_PASSWORD", "DFGHFHJGJH"
} | Set-Content $_.FullName
}
}
Or find all files that includes "AVEVAScripts" in it's name, then check if their full path includes "Running Scripts"
Get-ChildItem -Filter "AVEVAScripts*" -Path "C:\temp\Database Scripts" -Recurse |
Where-Object { $_.FullName -like "*Running Scripts*" } |
ForEach-Object {
(Get-Content $_.FullName) | ForEach-Object {
$_ -replace "DATABASE_USER","fhghjgj" -replace "DATABASE_PASSWORD", "DFGHFHJGJH"
} | Set-Content $_.FullName
}

Related

Write a script to sort words in alphabet order from specific file and put them into 26 text files named A.txt, B.txt, and so on up to Z.txt

I need to sort words alphabetically from a specific file and put them into 26 text files named A.txt, B.txt and so on up to Z.txt.
$Content = Get-Content ".\\1.txt"
$Content = ($Content.Split(" .,:;?!/()\[\]{}-\`\`\`"")|sort)
$linecount = 0
$filenumber = 0
$destPath = "C:\\test"
$destFileSize = 26
$Content |Group {$_.Substring(0,1).ToUpper()} |ForEach-Object {
$path = Join-Path $destPath $_.Name
$\_.Group |Set-Content $path
}
$Content | % {
Add-Content $destPath$filenumber.txt "$\_"
$linecount++
If ($linecount -eq $destFileSize) {
$filenumber++
$linecount = 0
}
}
You could do something like this, but this also could mean some files may not be written if there are no words beginning with a certain letter found in the file:
$destPath = "D:\test"
(Get-Content -Path 'D:\Test\Lorem.txt' -Raw) -split '\W' -ne '' |
Group-Object {$_.Substring(0,1).ToUpperInvariant()} |
Where-Object {$_.Name -cmatch '[A-Z]'} | ForEach-Object {
$_.Group | Sort-Object | Set-Content -Path (Join-Path -Path $destPath -ChildPath ('{0}.txt' -f $_.Name))
}
If you always want exactly 26 files even if some may contain nothing, use this instead
$destPath = "D:\test"
$wordGroups = (Get-Content -Path 'D:\Test\Lorem.txt' -Raw) -split '\W' -ne '' |
Group-Object {$_.Substring(0,1).ToUpperInvariant()}
foreach ($char in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' -split '(.)' -ne '')) {
$outFile = Join-Path -Path $destPath -ChildPath ('{0}.txt' -f $char)
$group = $wordGroups | Where-Object { $_.Name -eq $char }
if ($group) { $group.Group | Sort-Object | Set-Content -Path $outFile } # output the found words
else { $null | Set-Content -Path $outFile } # or create an empty file
}
The Where-Object {$_.Name -cmatch '[A-Z]'} clause makes it ignore words starting with some other character than A to Z

How to replace text in multiple file in many folder using powershell

I have many folder
ex: folder1,folder2,folder3... about folder100
In those folder have many files
ex: 1.html,2.html,3.html,4.html...about 20.html
I want to replace some text in those all html file in all folder
but not all text i want to replace is same.
ex:(for 1.html, i want to replace ./1_files/style.css to style.css) and (for 2.html, i want to replace ./2_files/style.css to style.css)....
So i try something like this and it work well
Get-ChildItem "*\1.html" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace './1_files/style.css', 'style.css' | Set-Content $_
}
Get-ChildItem "*\2.html" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace './2_files/style.css', 'style.css' | Set-Content $_
}
Get-ChildItem "*\3.html" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace './3_files/style.css', 'style.css' | Set-Content $_
}
Get-ChildItem "*\4.html" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace './4_files/style.css', 'style.css' | Set-Content $_
}
but i have to write many of those code "\4.html" "\5.html" "*\6.html" ...
i try this but it do not work
Do {
$val++
Write-Host $val
$Fn = "$val.html"
Get-ChildItem "*\$Fn" -Recurse | ForEach-Object -Process {
(Get-Content $_) -Replace './$val_files/style.css', 'style.css' |
Set-Content $_
}
} while($val -ne 100)
Please show me correct way to do..loop replace
thanks you
Assuming all your subfolders can be found inside one source folder path, you can do below to do the replacement in all those files:
# the path where all subfolders and html files can be found
$sourcePath = 'X:\Wherever\Your\Subfolders\Are\That\Contain\The\Html\Files'
Get-ChildItem -Path $sourcePath -Filter '*.html' -Recurse -File |
# filter on html files that have a numeric basename
Where-Object {$_.BaseName -match '(\d+)'} | ForEach-Object {
# construct the string to repace and escape the regex special characters
$replace = [regex]::Escape(('./{0}_files/style.css' -f $matches[1]))
# get the content as one single multiline string so -replace works faster
(Get-Content -Path $_.FullName -Raw) -replace $replace, 'style.css' |
Set-Content -Path $_.FullName
}

Powershell: Error while replacing the sub-string in a file

I am trying to replace some of the sub-strings with some values across multiple files. I have written this code to do so.
$dirPath = 'C:\repos\sync_cpc_cva\ExpressV2\Parameters\AG08\KeyVault'
$ConfigPath = 'C:\repos\sync_cpc_cva\config.json'
$lookupTable = #{}
(Get-Content -Raw -Path $configPath | ConvertFrom-Json).psobject.properties | Foreach { $lookupTable[$_.Name] = $_.Value }
Get-ChildItem -Path $dirPath -Recurse -Filter *.json |
Foreach-Object {
Get-Content $_.FullName | ForEach-Object {
$line = $_
$lookupTable.GetEnumerator() | ForEach-Object {
if($line -match $_.Key) {
$line = $line -replace $_.Key, $_.Value
}
}
$line
} | Set-Content -Path $_.FullName
}
If I print the content, it has replaced all the values correctly, however, it is unable to set the contents into the same file. And I am getting following error while running the code :
Set-Content : The process cannot access the file
'C:\repos\sync_cpc_cva\ExpressV2\Parameters\AG08\KeyVault\KeyVault.USNat.json' because it is being used by another process.
At C:\repos\sync_cpc_cva\filltest.ps1:22 char:9
+ } | Set-Content -Path $_.FullName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-Content], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.SetContentCommand
Any idea how can I replace the sub-strings in the same file?
You have several inner foreach-object loops, so you modify the $_ operator while being used. I dont think this can work. Revolve it like this:
$lookupTable = #{}
(Get-Content -Raw -Path $configPath | ConvertFrom-Json).psobject.properties | Foreach { $lookupTable[$_.Name] = $_.Value }
$files = Get-ChildItem -Path $dirPath -Recurse -Filter *.json
foreach ($file in $files) {
$content = Get-Content $file.FullName
for($i=0;$i -lt $content.length; $i++) {
$lookupTable.GetEnumerator() | ForEach-Object {
$content[$i] = $content[$i] -replace $_.Key, $_.Value
}
}
$content | Set-Content $file.FullName
}

Set-Content blanking files

I have the following script that is supposed to replace two keywords in a few SQL and batch scripts and then return them to the original:
# Modify TRIS 5 Scripts to account for database names used
$configFiles = Get-ChildItem (Join-Path $PSScriptRoot "\tris5scripts\") -Rec
foreach ($file in $configFiles) {
(Get-Content $file.PSPath) |
ForEach-Object { $_ -replace "TRISDemo4113", $databaseName } |
Set-Content $file.PSPath
ForEach-Object { $_ -replace "internal", $tris5Name } |
Set-Content $file.PSPath
}
cmd.exe (Join-Path $PSScriptRoot "\tris5scripts\execAll.cmd")
cmd.exe (Join-Path $PSScriptRoot "\tris5scripts\Prepare Dashboard Statistics.cmd")
if ($databaseName -ne "TRISDemo4113" -or $tris5Name -ne "internal") {
$configFiles = Get-ChildItem (Join-Path $PSScriptRoot "tris5scripts") -Rec
foreach ($file in $configFiles) {
(Get-Content $file.PSPath) |
ForEach-Object { $_ -replace $databaseName, "TRISDemo4113" } |
Set-Content $file.PSPath
ForEach-Object { $_ -replace $tris5Name, "internal" } |
Set-Content $file.PSPath
}
}
What is happening though is that the script makes every file in this folder blank. I'm not sure how as I have used this exact code snippet in another script and it works fine. It seems to get to the two cmd.exe calls and does nothing because every file is blank now.
All I am trying to do is change those two values in the files:
"TRIS4133" → $databaseName
"internal" → $tris5Name

How to exclude directory in Get-ChildItem results?

My script is doing what I need it to do, but I would like to be able to exclude certain folders.
In this case, it would be \york\SedAwk\ and \york\_ROT\.
Now, if I only put one folder in the $exclude variable, it works as expected. It's when I put both (or more) that it excludes neither, and throws no errors either when running.
Here is the script:
param(
[string]$pattern,
[string]$path
)
$exclude = #('*\york\SedAwk\*','*\york\_ROT\*')
Get-ChildItem -path $path -Recurse -Filter *.html |
Where-Object{
ForEach-Object {
If (Get-Content $_.FullName | Select-String -Pattern "<h2>Stay Connected") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Stay Connected" -Quiet
}
ElseIf (Get-Content $_.FullName | Select-String -Pattern "<h2>Soyez branch") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Soyez branch" -Quiet
}
Else {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<\/main>" -Quiet
}
}
} |
Select Fullname | ?{$_.FullName -notlike $exclude}
And here is how I run it:
.\FindStringContent.ps1 -pattern "list-unstyled" -path "w:\test\york" | Export-CSV "C:\Tools\exclude.csv"
I don't like using the -Exclude parameter because it's not file/folder specific, if you have a file and a folder that matches the string you're excluding they'll both be excluded.
When i'm excluding files i exclude them based on the FullName property which you could put in your ForEach to check if any of the files is in your $exclude variable:
param(
[string]$pattern,
[string]$path
)
$exclude = 'SedAwk','_ROT'
Get-ChildItem -path $path -Recurse -Filter *.html |
Where-Object{$_.FullName -notlike $exclude -and ForEach-Object {
If ($exclude -notcontains $_.FullName) {
If (Get-Content $_.FullName | Select-String -Pattern "<h2>Stay Connected") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Stay Connected" -Quiet
}
ElseIf (Get-Content $_.FullName | Select-String -Pattern "<h2>Soyez branch") {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Soyez branch" -Quiet
}
Else {
Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<\/main>" -Quiet
}
}
}
} | Select Fullname
Included suggested changes by TheMadTechnician