Powershell Set-Content is duplicating lines in .ini file - powershell

Go easy on me, first time posting.
I'm trying to use Powershell to Get-Content from an INI file. Particularly, I need to change two separate lines in the file. It runs, but instead of just replacing those 2 lines, it duplicates everything. It also doesn't replace the line I'm trying to tell it to replace, but instead it just adds my new line leaving the original in as well.
$FilePath = "C:\Users\folder\*.ini"
(Get-Content $FilePath) |
ForEach-Object {
$_ -replace "MailBell=0","MailBell=1"
$_ -replace "MailWindow=0","MailWindow=1"
} |
Set-Content $FilePath
There is a look at the code. Any help is greatly appreciated.

Related

How can I add a line break for every tilde found within the contents of several files found at a path?

I would like to use PowerShell to add a line break for every tilde it finds in a file.
The source could contain main .in files which contain tildes.
I have this script so far, and could benefit by some assistance in how to tweak it.
This will work for one file, but not for many:
(Get-Content -Path '.\amalgamatedack.in') |
ForEach-Object {$_.Replace('~', "~`r`n")} |
Set-Content -Path '.\amalgamatedack.in'
You can use Get-ChildItem to find all your .in files, then follow the same logic, just replace the input and output hardcoded file name for the absolute path of each file (.FullName property).
Your code could also benefit by using Get-Content -Raw, assuming these files are not very big and they fit in memory, reading the content as single multi-line string is always faster.
# If you need to search recursively for the files use `-Recurse`
Get-ChildItem path\to\sourcefolder -Filter *.in | ForEach-Object {
($_ | Get-Content -Raw).Replace('~', "~`r`n") |
Set-Content -Path $_.FullName
}

Get-Content Measure-Object Command : Additional rows are added to the actual row count

This is my first post here - my apologies in advance if I didn't follow a certain etiquette for posting. I'm a newbie to powershell, but I'm hoping someone can help me figure something out.
I'm using the following powershell script to tell me the total count of rows in a CSV file, minus the header. This generated into a text file.
$x = (Get-Content -Path "C:\mysql\out_data\18*.csv" | Measure-Object -Line).Lines
$logfile = "C:\temp\MyLog.txt"
$files = get-childitem "C:\mysql\out_data\18*.csv"
foreach($file in $files)
{
$x--
"File: $($file.name) Count: $x" | out-file $logfile -Append
}
I am doing this for 10 individual files. But there is just ONE file that keeps adding exactly 807 more rows to the actual count. For example, for the code above, the actual row count (minus the header) in the file is 25,083. But my script above generates 25,890 as the count. I've tried running this for different iterations of the same type of file (same data, different days), but it keeps adding exactly 807 to the row count.
Even when running only (Get-Content -Path "C:\mysql\out_data\18*.csv" | Measure-Object -Line).Lines, I still see the wrong record count in the powershell window.
I'm suspicious that there may be a problem specifically with the csv file itself? I'm coming to that conclusion since 9 out of 10 files generate the correct row count. Thank you advance for your time.
To measure the items in a csv you should use Import-Csv rather than Get-Content. This way you don't have to worry about headers or empty lines.
(Import-Csv -Path $csvfile | Measure-Object).Count
It's definitely possible there's a problem with that csv file. Also, note that if the csv has cells that include linebreaks that will confuse Get-Content so also try Import-CSV
I'd start with this
$PathToQuestionableFile = "c:\somefile.csv"
$TestContents = Get-Content -Path $PathToQuestionableFile
Write-Host "`n-------`nUsing Get-Content:"
$TestContents.count
$TestContents[0..10]
$TestCsv = Import-CSV -Path $PathToQuestionableFile
Write-Host "`n-------`nUsing Import-CSV:"
$TestCsv.count
$TestCsv[0..10] | Format-Table
That will let you see what Get-Content is pulling so you can narrow down where the problem is.
If it is in the file itself and using Import-CSV doesn't fix it I'd try using Notepad++ to check both the encoding and the line endings
encoding is a drop down menu, compare to the other csv files
line endings can be seen with (View > Show Symbol > Show All Characters). They should be consistent across the file, and should be one of these
CR (typically if it came from a mac)
LF (typically if it came from *nix or the internet)
CRLF (typically if it came from windows)

Removing blank lines from text file using batch

Recently this question was posted on stackoverflow, I have a similar problem as J. Williams except I only need to remove empty lines (removing spaces would not hurt the program though, it just isn't necessary). When I tried his original as well as the solution compo gave it only cleared the file instead of removing extra lines. I'm using it by itself in a batch file.
Example:
I need this:
Joe
Bob
Mark
Frank
Dutch
(blank line here too)
to become this:
Joe
Bob
Mark
Frank
Dutch
I'm open to attaching such a solution to this powershell script too, as it is what is giving me the blank lines: (Get-Content friends.txt) | Where-Object {$_ -notmatch "\bJoe\b"} | Set-Content friends.txt Thank's for your help.
This should work for you - in short, it reads all the lines of the file, then writes back only the lines with something in it to the file.
$friends = Get-Content friends.txt
$friends | Where-Object { $_ } | Set-Content friends.txt
If it's a relatively small file:
(Get-Content $infile) -match '\S' | Set-Content $infile
If it's too large to read into memory all at once:
Get-Content $infile -ReadCount 1000 |
ForeachObject {
$_ -match '\S' |
Add-Content $outfile
}
Another PowerShell method would be to use the Select-String cmdlet using the regex pattern .+ which means one or more of any character. Also if using Set-Content be sure to use the -NoNewLine parameter to prevent the unwanted blank line at the end. (Requires PS5+)
Select-String -Path C:\example.txt -Pattern '.+' |
Select-Object -ExpandProperty line |
Set-Content C:\exampleoutput.txt -NoNewline

Replacing contents of a text file using PowerShell

I've looked all around this site and can't quite seem to find anything that fits my situation. Basically, I am trying to write an addition to the NETLOGON file that will replace text in a text file on all of our users' desktops. The current text is static across the board.
The text I want it changed to will be unique to each user. I want to change the current text (user1) to the users AD username (i.e. johnd, janed, etc.). I am using Windows Server 2008 R2 and all the workstations are Windows 7 Professional SP1 64 bit.
Here's what I have tried so far (with a few variables, which none have worked for one reason or the other):
gc c:\Users\%USERNAME%\desktop\VPN.txt' -replace "user1",$env:username | out-file c:\Users\%USERNAME%\desktop\VPN.txt
I didn't get an error, but it also did not go back to the normal "PS C:>" prompt, just ">>>" and the file did not change as anticipated.
If that is how you have the code exactly then I suppose it is because you have an opening single quote without a closing one. You are still going to have two other problems and you have one answer in your code. The >>> is the line continuation characters because the parser knows that the code is not complete and giving you the option to continue with the code. If you were purposely coding a single line on multiple lines you would consider this a feature.
$path = "c:\Users\$($env:username)\desktop\VPN.txt"
(Get-Content $path) -replace "user1",$env:username | out-file $path
Closed the path in quotes and used a variable since you called the path twice.
%name% is used in command prompt. Environment variables in PowerShell use the $env: provider which you did you once in your snippet.
-replace is a regex replaced tool that can work against Get-Content but you need to capture the result in a sub expression first.
Secondly with -replace is for regex and your string is not regex based you could just use .Replace() as well.
Set-Content is generally preferred over Out-File for performance reasons.
All that being said...
you could also try something like this.
$path = "c:\Users\$($env:username)\desktop\VPN.txt"
(Get-Content $path).Replace("user1",$env:username) | Set-Content $path
Do you want to only replace the first occurrence?
You could use a little regex here with a tweak in how you get the use Get-Content
$path = "c:\Users\$($env:username)\desktop\VPN.txt"
(Get-Content $path | Out-String) -replace "(.*?)user1(.*)",('$1{0}$2' -f $env:username) | out-file $path
Regex will match the entire file. There are two groups which it captures.
(.*?) - Up until the first "user1"
(.*) - Everything after that
Then we use the format operator to sandwich the new username in between those capture groups.
Use:
(Get-Content $fileName) | % {
if ($_.ReadCount -eq 1) {
$_ -replace "$original", "$content"
}
else {
$_
}
} | Set-Content $fileName

Replace text between quotes in XML

I'm trying to find a way to change unknown text (could be anything) in an XML file for a printer migration.
The text that is in question is
PrintProcessor="hpcpp111"
The Print Processor section could contain anything as this varies depending on printer model, type and driver. I would prefer to use powershell if possible as I am trying to understand scripting and how it all works, but I find it a little confusing. I may need to manually edit thousands of these files as we are migrating 5,500 printers.
I have found some code that gets it close for example
function Reset-InfoPathTemplateLink {
Param(
[string]$FilePath,
[string]$FileExtension,
[string]$OldPath,
[string]$NewPath
)
$files = Get-ChildItem $FilePath -Filter $FileExtension
foreach ($file in $files) {
(Get-Content $file.fullname) |
ForEach-Object {$_ -replace $OldPath,$NewPath} |
Set-Content $file.fullname
} #end foreach
} #end function
and if I dot-source it and then run this command
Reset-InfoPathTemplateLink -FilePath "c:\test2" -FileExtension ".xml" -OldPath "PrintProcessor=""" -NewPath "PrintProcessor='"WinPrint"'"
The WinPrint gets added to the beginning of the current print processor, which isnt ideal. If anyone has tips on how to get this to work, or if they can suggest a better method of doing this I would appreciate it
this is how you can use PowerShell to replace a pattern within a text file:
$path="c:\myPath.txt"
(Get-Content $path) -replace '(PrintProcessor=")(.*)(")','$1WinPrint$3' | Set-Content $path