Delete a line in file if it is empty in powershell - powershell

How to delete a empty line in file?
When i searched for it , people are creating another file to move non empty lines like follows
gc c:\FileWithEmptyLines.txt | where {$_ -ne ""} > c:\FileWithNoEmptyLines.txt
Is there any way to delete the line in the source file itself?

Why can't you save it back to the same file? Split it into 2 lines:
$var = gc c:\PST\1.txt | Where {$_ -ne ""}
$var > c:\pst\1.txt

Skip lines that match a space, a tab or a line break:
(Get-Content c:\FileWithEmptyLines.txt) | `
Where-Object {$_ -match '\S'} | `
Out-File c:\FileWithEmptyLines.txt
UPDATE: for multiple files:
$file = Get-ChildItem -Path "E:\copyforbuild*xcopy.txt"
foreach ($f in $file)
{
(Get-Content $f.FullName) | `
Where-Object {$_ -match '\S'} | `
Out-File $f.FullName
}

Related

Get-ChildItem Zero Results Output

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

Avoid blank line on Out-File

How can I avoid getting a blank line at the end of an Out-File?
$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher([adsi]'')
$DirSearcher.Filter = '(&(objectClass=Computer)(!(cn=*esx*)) (!(cn=*slng*)) (!(cn=*dcen*)) )'
$DirSearcher.FindAll().GetEnumerator() | sort-object { $_.Properties.name } `
| ForEach-Object { $_.Properties.name }`
| Out-File -FilePath C:\Computers.txt
I have tried several options and none of them seem to do anything, they all still have a blank line at the end.
(get-content C:\Computers.txt) | where {$_ -ne ""} | out-file C:\Computers.txt
$file = C:\Computers.txt
Get-Content $file | where {$_.Length -ne 0} | Out-File "$file`.tmp"
Move-Item "$file`.tmp" $file -Force
Use [IO.File]::WriteAllText:
[IO.File]::WriteAllText("$file`.tmp",
((Get-Content $file) -ne '' -join "`r`n"),
[Text.Encoding]::UTF8)
Often when you're looking to see if strings have no character data, you will want to use String.IsNullOrWhiteSpace():
Get-Content $file | Where-Object { ![String]::IsNullOrWhiteSpace($_) } | Out-File "$file`.tmp"
this the best solution for the avoiding the empty line at the end of txt file using powershell command
Add-Content C:\Users\e5584332\Desktop\CSS.txt "Footer | Processed unique data || $count " -NoNewline

Combine file IO for -replace and Set-Content in PowerShell

I have the following script:
$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
# Find and replace the dash cased the contents of the files
(Get-Content $file.PSPath) |
Foreach-Object {$_ -replace "my-project-name", '$appNameDashCased$'} |
Set-Content $file.PSPath
# Find and replace the dash cased the contents of the files
(Get-Content $file.PSPath) |
Foreach-Object {$_ -replace "MyProjectName", '$appNameCamelCased$'} |
Set-Content $file.PSPath
# Find and replace the dash cased the contents of the files
(Get-Content $file.PSPath) |
Foreach-Object {$_ -replace "myProjectName", '$appNamePascalCased$'} |
Set-Content $file.PSPath
}
It takes a file and does some replacing, then saves the file. Then it takes the same file and does some more replacing then saves the file again. Then it does it one more time.
This works, but seems inefficient.
Is there a way to do all the replacing and then save the file once?
(If possible, I would prefer to keep the readable style of PowerShell.)
Sure, just chain your replaces inside the ForEach-Object block:
$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object {
# Find and replace the dash cased the contents of the files
$_ -replace "my-project-name", '$appNameDashCased$' `
-replace "MyProjectName", '$appNameCamelCased$' `
-replace "myProjectName", '$appNamePascalCased$'
} |
Set-Content $file.PSPath
}
This can be done, and is actually far simpler than what you're doing. You can chain the -Replace command as such:
$allFiles = Get-ChildItem "./" -Recurse | Where { ($_.Extension -eq ".ts")}
foreach($file in $allFiles)
{
# Find and replace the dash cased the contents of the files
(Get-Content $file.PSPath) -replace "my-project-name", '$appNameDashCased$' -replace "StringB", '$SecondReplacement$' -replace "StringC", '$ThirdReplacement$' | Set-Content $file.PSPath
}

Using PowerShell to remove lines from a text file if it contains a string

I am trying to remove all the lines from a text file that contains a partial string using the below PowerShell code:
Get-Content C:\new\temp_*.txt | Select-String -pattern "H|159" -notmatch | Out-File C:\new\newfile.txt
The actual string is H|159|28-05-2005|508|xxx, it repeats in the file multiple times, and I am trying to match only the first part as specified above. Is that correct? Currently I am getting empty as output.
Am I missing something?
Suppose you want to write that in the same file, you can do as follows:
Set-Content -Path "C:\temp\Newtext.txt" -Value (get-content -Path "c:\Temp\Newtext.txt" | Select-String -Pattern 'H\|159' -NotMatch)
Escape the | character using a backtick
get-content c:\new\temp_*.txt | select-string -pattern 'H`|159' -notmatch | Out-File c:\new\newfile.txt
Another option for writing to the same file, building on the existing answers. Just add brackets to complete the action before the content is sent to the file.
(get-content c:\new\sameFile.txt | select-string -pattern 'H`|159' -notmatch) | Set-Content c:\new\sameFile.txt
You don't need Select-String in this case, just filter the lines out with Where-Object
Get-Content C:\new\temp_*.txt |
Where-Object { -not $_.Contains('H|159') } |
Set-Content C:\new\newfile.txt
String.Contains does a string comparison instead of a regex so you don't need to escape the pipe character, and it's also faster
The pipe character | has a special meaning in regular expressions. a|b means "match either a or b". If you want to match a literal | character, you need to escape it:
... | Select-String -Pattern 'H\|159' -NotMatch | ...
This is probably a long way around a simple problem, it does allow me to remove lines containing a number of matches. I did not have a partial match that could be used, and needed it to be done on over 1000 files.
This post did help me get to where I needed to, thank you.
$ParentPath = "C:\temp\test"
$Files = Get-ChildItem -Path $ParentPath -Recurse -Include *.txt
$Match2 = "matchtext1"
$Match2 = "matchtext2"
$Match3 = "matchtext3"
$Match4 = "matchtext4"
$Match5 = "matchtext5"
$Match6 = "matchtext6"
$Match7 = "matchtext7"
$Match8 = "matchtext8"
$Match9 = "matchtext9"
$Match10 = "matchtext10"
foreach ($File in $Files) {
$FullPath = $File | % { $_.FullName }
$OldContent = Get-Content $FullPath
$NewContent = $OldContent `
| Where-Object {$_ -notmatch $Match1} `
| Where-Object {$_ -notmatch $Match2} `
| Where-Object {$_ -notmatch $Match3} `
| Where-Object {$_ -notmatch $Match4} `
| Where-Object {$_ -notmatch $Match5} `
| Where-Object {$_ -notmatch $Match6} `
| Where-Object {$_ -notmatch $Match7} `
| Where-Object {$_ -notmatch $Match8} `
| Where-Object {$_ -notmatch $Match9} `
| Where-Object {$_ -notmatch $Match10}
Set-Content -Path $FullPath -Value $NewContent
Write-Output $File
}
If you anyone having this issue while doing what suggested by Robert Brooker-
*These files have different encodings. Left file: Unicode (UTF-8) with signature. Right file: Unicode (UTF-8) without signature. You can resolve the difference by saving the right file with the encoding Unicode (UTF-8) with signature.* with Set-Content
use -Encoding UTF8
so like this
(get-content c:\new\sameFile.txt | select-string -pattern 'H`|159' -notmatch) | Set-Content c:\new\sameFile.txt -Encoding UTF8

Powershell if changed Set-Content

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