I have a PowerShell script that I use to change text in a number of files. The following script will work & changes the text as expected.
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
(Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
Set-Content $_
}
The problem is though, it changes every file that it opens, so everything has a timestamp of when the job was run even if nothing was changed.
I have tried something similar to what is here but it gives me an error:
The term 'if' is not recognized as the name of a cmdlet, function, etc...
Here is the code I am trying to run:
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
$b = ($a = Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
if (Compare $a $b -PassThru) {
$b | Set-Content $_
}
}
I know that the code isn't right, but if I move it inside the ForEach-Object, it won't run either.
What I want to do is to use the Set-Content statement only if the contents of the file have changed. Would appreciate any thoughts as to how best to do this.
What you can do is look for the string before getting and setting content. Something like:
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
If(Select-String -Path $_ -SimpleMatch $old -quiet){
(Get-Content $_) |
ForEach-Object {$_ -replace $old $new } |
Set-Content $_
}
}
Related
I would like to change _ to - in all .md files from folder FOO. The code below does what I need but I don't how to save results in folder FOO or some other...
$mdfiles = gci *.md
gc $mdfiles | ForEach-Object {if ( $_ -match '^!') {$_ -replace '_', '-'} else {$_}} | out-file ...
A ForEach-Object is needed to iterate over the file names as well. Ternary expressions are in PowerShell Core, but I am not sure about Windows PowerShell. This is not tested, but might give a start.
Get-ChildItem -File -Path '.' -Filter '*.md' |
ForEach-Object {
$OutFile = ".\foo\$($_.Name)"
Get-Content -Path $_.FullName |
ForEach-Object { ($_ -match '^!') ? ($_ -replace '_','-') : ($_) } |
Out-File -FilePath $OutFile
}
Also, it is bad practice to use alias commands in a stored script.
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
}
Using PowerShell, I have created a script that adds headers to a CSV, select unique value within specified columns, and exports it as a new CSV.
That script is:
import-csv -Header (1..39) -Path 'J:\consult evv\splitfile_385.csv' | select '30', '31', '39' -Unique | Export-Csv -Path "C:\Users\CFOSTER\Desktop\stuff\modsplitfile_385.csv" -NoTypeInformation
This script only works for one item: splitfile_385.csv. I'd like to use this for all files in a directory.
I can loop through items in the specified path but am having trouble combining the loop with the script above.
Currently, I have:
$files = Get-ChildItem "J:\consult evv"
for ($i=0; $i -lt $files.Count; $i++) {
$outfile = "C:\Users\CFOSTER\Desktop\Stuff\new" + $files[$i]
Get-Content $files[$i].FullName | Where-Object { !($_ -match 'step4' -or $_ -match 'step9') } | import-csv -Header (1..39) -Path $files[$i].FullName | select '30', '31', '39' -Unique | Set-Content $outfile
}
Using this gives me the error: import-csv : You must specify either the -Path or -LiteralPath parameters, but not both.
How can I combine my script with a loop for all files in a directory?
You can use ForEach-Object and import one at a time.
Get-ChildItem "C:\CSV Files\*.csv" | ForEach-Object {
Import-Csv $_ | Where-Object { ... }
}
If you want to output to a new CSV file, make sure the output filename doesn't match the pattern used with Get-ChildItem or you'll run into trouble.
try somethng like this:
Get-ChildItem "J:\consult evv" -file -Filter "*.csv" | %{
$outfile = "C:\Users\CFOSTER\Desktop\Stuff\new" + $_.Name
Get-Content $_.FullName | select -skip 1 | Where { !($_ -match 'step4' -or $_ -match 'step9') } |
ConvertFrom-Csv -Header (1..39) | select '30', '31', '39' -Unique | Out-File $outfile -Append
}
I have an issue that I cannot resolve no matter which way I am wrapping it up. I am including my latest code which is not giving me the desired outcome and the code for a solution that does work but for only one file at a time. I cannot work out how to loop through each of the files automatically however.
In a nutshell, I have a directory with many CSV files some of the entries within the CSVfile have a negative value (-) I need to remove this minus sign in all instances.
Now what works is if I use the following (on a single file)
$content = Get-Content "L:\Controls\BCR\0001cash.csv" | ForEach {$_ -replace $variable, ""} | Set-Content "L:\controls\bcr\0001temp.csv"
What I am trying to do is iterate through the many thousand of these objects automatically and not have to refer to them individually.
I started with:
$Directory = "L:\Controls\BCR\"
$variable = "-"
$suffix = ".tmp"
To define the directory, minus symbol that I want to remove and the suffix of the file I want to change to...
$Files = Get-ChildItem $Directory | Where-Object {$_.Extension -like "*csv*"} | Where-Object {$_.Name -like "*cash*"}
Is obtaining each of the files that I wish to work with
And I am then working with
ForEach ($File in $Files) { Get-Content $Files | ForEach {$_ -replace $variable, ""} | Set-Content {$_.Basename + $Variable}
The results however are nothing...
At a loss? Anyone???
$Directory = "L:\Controls\BCR\"
$variable = "-"
$suffix = ".tmp"
$Files = Get-ChildItem $Directory | Where-Object {$_.Extension -like "*csv*"} | Where-Object {$_.Name -like "*cash*"}
$process = ForEach ($File in $Files) { Get-Content $Files | ForEach {$_ -replace $variable, ""} | Set-Content {$_.BaseName + $suffix}
}
You are using the wrong variable in the Get-Content cmdlet ($Files instead of $File). Also You can simplify your script:
$Directory = "L:\Controls\BCR\"
$variable = "-"
$suffix = ".tmp"
Get-ChildItem $Directory -Filter '*cash*csv' |
ForEach-Object {
(Get-Content $_ -Raw) -replace $variable |
Set-Content {$_.BaseName + $suffix}
}
So i have this powershell...
pushd "C:\PSF\Move to V6\DTT Files"
$configFiles = Get-ChildItem . *.dtt -rec
foreach ($file in $configFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "OLD", "NEW" } |
Set-Content $file.PSPath
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "OLD2", "NEW2" } |
Set-Content $file.PSPath
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace "OLD3", "NEW3" } |
Set-Content $file.PSPath
}
What i am hoping to do is have it pop up with a few boxes asking what you want:
New, New2 and New3 to be specificly.
I am very new to powershell so i am clueless when it comes to doing something like that. (Or even if you can)
If it's not possible, i will accept suggestions for other things i can do in place of doing this.
If you're using PowerShell v3+ then I like using Out-GridView for this purpose:
$choices = #('NEW', 'NEW2', 'NEW3')
$selection = $choices | Out-GridView -Title 'Select Replacement' -OutputMode Single
It's simple, effective, intuitive, and built-in.