2

I'm having issues with line endings.  I have a file tracked by git.  Then I'm trying to recreate that file with PowerShell with $content | Out-File $location and git is tracking a change in the line ending at EOF.

If in the terminal I run file ./somefile.sql (the file already in git) I get an output ./somefile.sql ASCII text, with CRLF line terminators

Running cat -ve ./somefile.sql The last 2 lines of the file shows

^M$
END^M$   #'END' is actual text in the file

If in the terminal I run file ./dupfile.sql (the file created by PowerShell) I get an output ./dupfile.sql ASCII text, with CRLF, LF line terminators

Running cat -ve ./dupfile.sql The last 2 lines of the file shows

^M$
END$ 

If I change Out-File to use $content | Out-File $location -NoNewLine and check the dupfile outputs again I get: ASCII text, with CRLF line terminators ...but...

^M$
END%

How can I use Out-File to write $content and get a ^M$ ending like the one I have in git?

Frankie
  • 11,508
  • 5
  • 53
  • 60

1 Answers1

2

Use the following (assuming that $content contains a string):

Set-Content -NoNewLine $location -Value ($content + "`r`n")

The solution above assumes that $content is a single, multiline string and appends a CRLF sequence to it (represented as "`r`n", an expandable string with escape sequences), then writes it as-is to the target file, using -NoNewLine. Read on for background information.


If you know you're dealing with strings, Set-Content performs better than Out-File.

Both cmdlets exhibit the same newline handling (though their default character encoding differs in Windows PowerShell, fortunately no longer in PowerShell (Core) 7+, where (BOM-less) UTF-8 is consistently used):

  • With multiple input objects, the platform-native newline sequence is inserted between the (stringified) objects on saving, i.e. CRLF on Windows, LF on Unix - as reflected in [Environment]::NewLine.

  • By default, a trailing platform-native newline is appended.

Regarding -NoNewLine:

  • -NoNewLine doesn't just suppress a trailing newline, but also newlines between multiple input objects, if applicable.

  • If the input is a single, multiline string, you can use -NoNewLine to write it to a file as-is to a file (which means that that string's trailing-newline-or-not status is preserved as is). With multiple strings, however, you effectively get string concatenation without a separator.

Note that Get-Content has a -Delimiter parameter, which Out-File and Set-Content / Add-Content lack.

GitHub issue #3855 proposes introducing this parameter, which would allow you request use of a non-native newline sequence on demand, such as -Delimiter "`r`n" on Unix, and -Delimiter "`n" on Windows.

mklement0
  • 382,024
  • 64
  • 607
  • 775