1

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.

Mark Deven
  • 550
  • 1
  • 9
  • 21
  • Note that I had to enter `(blank line here too)` because it would not let me select a blank line as code when it is at the end of a script. – Mark Deven Nov 09 '17 at 19:59
  • `(Get-Content friends.txt) | Where-Object {$_ -notmatch "^\s*$" -and $_ -notmatch "\bJoe\b" } | Set-Content friends.txt` - changes it to include a check that lines are not just whitespace from start to end. – TessellatingHeckler Nov 09 '17 at 20:10
  • Did you happen to read the help file for the `FOR` command? In particular this line: `Blank lines are skipped.` – Squashman Nov 09 '17 at 20:14

3 Answers3

4

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
Bryce McDonald
  • 1,760
  • 12
  • 22
  • 2
    If you are reading and writing to the same file in the pipeline you are going to get an error. If the file is small just wrap it up with braces to read in the whole file _before_ passing it down the pipeline. – Matt Nov 09 '17 at 20:36
  • You can put the content he provided in a file and run this code and it will work. Admittedly I doubt this solution would scale to large files well. Is that where it would error out? – Bryce McDonald Nov 09 '17 at 20:38
  • 1
    _Set-Content : The process cannot access the file 'M:\Scripts\friends.txt' because it is being used by another process._ Using the sample data in a file called friends.txt and the code in this answer. – Matt Nov 09 '17 at 20:39
  • 1
    100% my bad - I scrolled up through my history and set `Get-Content friends.txt` to `$x` before piping `$x` through. Updated answer for accuracy – Bryce McDonald Nov 09 '17 at 20:43
3

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
 }
mjolinor
  • 66,130
  • 7
  • 114
  • 135
0

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) -join [Environment]::NewLine |
    Set-Content C:\exampleoutput.txt -NoNewline
BenH
  • 9,766
  • 1
  • 22
  • 35
  • Small caveat would be if any of the lines contain whitespace they will satisfy the pattern. – Matt Nov 09 '17 at 20:38
  • 1
    when testing it (sample text file with 3 words, empty line, 2 words, it wil work, but add a new line at the end. adding the -nonewline, it will place all words on one line. – Paul Fijma Jul 12 '23 at 06:51
  • 1
    @PaulFijma Updated answer with information from: https://stackoverflow.com/a/45269244/6788803 – BenH Jul 12 '23 at 13:03