Search code examples
powershelltextcsv

Remove last line from file with Powershell


I am using

gc FileWithEmptyLines.txt | where {$_ -ne ""} > FileWithNoEmptyLines.txt

to remove the empty lines that SSRS puts at the bottom of my CSVs.

However, the last line, which has data on it, ends with a CRLF (as viewed in Notepad++) - and this is not removed, so technically there is still a blank line at the bottom of the file.

Is there a way to remove this CRLF from the last line (and keep the data intact, of course)?


Solution

  • If you already know that the very last thing of the file is a CRLF you want to get rid of (and you know the encoding too) you can go the quick route:

    $stream = [IO.File]::OpenWrite('foo.txt')
    $stream.SetLength($stream.Length - 2)
    $stream.Close()
    $stream.Dispose()
    

    This is an in-place truncation of the file. It works without reading all the file into memory (very nice if you have a very large file). It works for ASCII, Latin-* and UTF-8. It won't work that way for UTF-16 (you'd have to remove four bytes from the end, in that case).

    You can include an additional check that the last two bytes are really what you want to remove:

    $stream = [IO.File]::Open('foo.txt', [IO.FileMode]::Open)
    $stream.Position = $stream.Length - 2
    $bytes = 0..1 | %{ $stream.ReadByte() }
    $compareBytes = 13,10 # CR,LF
    if ("$bytes" -eq "$compareBytes") {
        $stream.SetLength($stream.Length - 2)
    }
    $stream.Close()
    $stream.Dispose()
    

    Again, adapt if you use another encoding, e.g. for UTF-16 you need to compare to either 0,10,0,13 or 10,0,13,0.

    Agreed, this is not very PowerShell-ey, but ever since I had to process a 700-MiB database dump I am wary of reading potentially large files into memory completely ;)