Caxton
Features Benchmarks Pricing Docs How it works Changelog Support About Download Free
Guides
All guides Large File Text Editors EmEditor for Mac UltraEdit Alternatives Notepad++ Alternatives Notepad for Mac File Too Large for VS Code CSV Editor for Mac Open a CSV File CSV Viewer for Mac Edit CSV Without Auto-Formatting Repair a Malformed CSV Remove Duplicate Rows Validate a CSV Transform a CSV Column Fixed-Width to CSV Sort a Large CSV CSV Too Big for Excel Open a Huge CSV Log Viewer for Mac Open a 10 GB Log Filter Large Log Files Jump to a Time in a Log Find & Replace in Huge Files Find & Replace Across Files Compare Two Text Files Open a SQL Dump Fix Garbled Text & Encoding Convert Line Endings Open a GBK or Big5 File Open a Large JSON File Numbers File Too Large

LF vs CRLF line endings, explained.

Every line in a text file ends with an invisible character or two, and Windows and macOS do not agree on which. The difference is harmless until a diff shows every line changed, a script refuses to run, or an import breaks on a character nobody can see. This page says what the endings are, how to find out which one a file uses, and how to convert it with tools that are already on a Mac.

Download Caxton for Free · 7-day free trial of Caxton Pro, no credit card required · 7 MB · macOS 13.0+

The short answer

The free way is dos2unix and unix2dos from Homebrew, or tr, sed and perl, which are already on every Mac and change only the invisible line-break bytes. Caxton, a native Mac editor for text and data files, shows a file's line ending in its status bar and Inspector, keeps it on every save, and converts a CSV's endings with CSV ▸ Repair ▸ Normalize Line Endings.

What are LF, CRLF and CR?

A line break is a control character at the end of a line. Apple's own documentation for scripting on the Mac describes the three conventions. Unix-style, which macOS uses: "each line in a text file ends with a newline character (character 10/0xA, often abbreviated LF)." Windows-style: "each line in a text file ends with both a carriage return and a line feed (character 13/0xD followed by character 10/0xA, often abbreviated CR/LF or CRLF)." And the old Mac style: "Many older Mac applications use 'Mac-style' line endings. This means that each line in a text file ends with a carriage return character (character 13/0xD, often abbreviated CR)." The dos2unix manual says the same from the other side: "In Mac text files, prior to Mac OS X, a line break was single Carriage Return (CR) character. Nowadays Mac OS uses Unix style (LF) line breaks."

So: LF is macOS and Linux, CRLF is Windows, and CR alone is the classic Mac OS of the 1990s, which you still meet in old exports and in some files written by old software.

How do I tell which line ending a file uses?

Three ways, two of them in the Terminal and one in Caxton.

file report.txt
# ASCII text, with CRLF line terminators

cat -ev report.txt | head -3
# a CRLF file shows ^M$ at the end of each line; an LF file shows $

od -c report.txt | head -3
# a CRLF file shows \r \n at the end of each line; an LF file shows \n

file names the terminators in its one-line description. cat -ev prints a $ at every line end and shows a carriage return as ^M, so a Windows file reads ^M$. od -c prints every byte as a character, with \r for the carriage return and \n for the line feed. In Caxton, open the file and look at the right end of the status bar: beside the encoding it shows the line ending, LF, CRLF or CR, for the file as a whole. The Inspector in the sidebar lists the same fact with the encoding, the BOM and the size. Both are Caxton Free.

Why do mixed or unexpected line endings cause trouble?

  • Git shows every line as changed. The Pro Git book explains the cause: "Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas macOS and Linux systems use only the linefeed character," and "many editors on Windows silently replace existing LF-style line endings with CRLF." When a file's endings change, every line's bytes change, so a diff marks every line. Git's core.autocrlf setting is the documented fix: set to true, Git "converts LF endings into CRLF when you check out code"; set to input, it will "convert CRLF to LF on commit but not the other way around." For a one-off look, git diff --ignore-cr-at-eol will "Ignore carriage-return at the end of line when doing a comparison," and after fixing a repository's attributes, git add --renormalize . rewrites the index.
  • Scripts fail to run. A shell script saved with CRLF endings has a carriage return at the end of its first line, right after the interpreter's name, so the system looks for an interpreter whose name ends in that character and reports that it does not exist. The script is fine; its line endings are not.
  • CSV imports break. A CSV with CR endings reads as one enormous line to a tool that expects LF, and a file with a mix of endings can split a row in two or glue two together. The CSV standard, RFC 4180, says each record is "delimited by a line break (CRLF)," and most tools accept LF as well, but a stray CR in the middle of a field is a repair job. Repair a malformed CSV on a Mac covers that case.

Free ways to convert line endings on a Mac

Every conversion below changes only the line-break bytes. The text on each line stays exactly as it was.

dos2unix and unix2dos

The Homebrew formula dos2unix is described as "Convert text between DOS, UNIX, and Mac formats," and the project's manual page calls it a "DOS/Mac to Unix and vice versa text file format converter." It converts in place, so keep a copy of anything precious.

brew install dos2unix
dos2unix report.txt        # CRLF to LF
unix2dos report.txt        # LF to CRLF
mac2unix old-export.txt    # CR to LF

tr, sed and perl, already on the Mac

tr -d '\r' < windows.txt > unix.txt                 # CRLF to LF, into a new file
sed $'s/$/\r/' unix.txt > windows.txt                # LF to CRLF, into a new file
perl -pi -e 's/\r\n/\n/g' report.txt                 # CRLF to LF, in place
perl -pi -e 's/\r/\n/g' old-export.txt               # CR to LF, in place

tr -d '\r' deletes every carriage return, which is exactly the CRLF-to-LF conversion when the file has no other carriage returns. The sed form uses the shell's $'...' quoting so that \r is a real carriage return. perl -pi edits the file in place; add a suffix, as in -pi.bak, to keep the original beside it.

What does Caxton do with line endings today?

Caxton shows the ending and keeps it. The status bar reports LF, CRLF or CR beside the encoding, the Inspector lists it with the file's other facts, and every edit and save keeps the document's own ending; Caxton's line operations split on the document's line ending only. There is no command in Caxton 2.2.0 that converts the line endings of a plain text file, so for a text file the commands above are the way. Two commands do convert in specific cases:

  • CSV ▸ Repair ▸ Normalize Line Endings rewrites a CSV's line endings consistently, with a preview of exact examples before it applies and one undo after, and it also gives the last row a line ending when it has none. Repairs change the file, so this is Caxton Pro.
  • File ▸ Combine Files… joins two or more files into one new document and lets you choose the line endings of the result: keep each file's own, or normalize them all to LF or CRLF. Writing a new document is Caxton Pro.

Caxton's Compare never compares line terminators, so a file and its CRLF copy show no differences, and the Compare window says so when the two sides use different endings; that is the quick way to confirm that a conversion changed nothing but the line breaks. Caxton Free.

See a file's line ending in the status bar, repair a CSV's endings with a preview, read any text file at any size.

Download Caxton for Free

7-day free trial of Caxton Pro, every feature, no credit card required. After it, Caxton Free keeps opening, searching and filtering at any size.

Frequently asked questions

Does converting line endings change the content?

No. A conversion replaces only the invisible line-break bytes at the end of each line; every character on the line stays exactly as it was. That is why a git diff that ignores carriage returns, or a Caxton Compare, which never compares line terminators, shows no differences between a file and its converted copy.

Why does git show every line as changed?

Because the line endings changed, and that changes the bytes of every line. The Pro Git book says many editors on Windows silently replace LF endings with CRLF. Git's core.autocrlf setting converts on the way in and out so the repository stays consistent, git diff --ignore-cr-at-eol compares without the carriage returns, and git add --renormalize . rewrites the index after the attributes are fixed.

Do Macs still use CR?

No. Apple's documentation describes the carriage return alone as the ending many older Mac applications used; macOS, like Linux, ends lines with the line feed, LF. You still meet CR in old exports, and mac2unix or perl converts them.

Which line ending should a CSV use?

RFC 4180, the CSV standard, delimits records with CRLF, and most tools, Caxton included, read LF just as well. What breaks imports is a mix, or a CR alone, which some tools read as one giant line. Keep a CSV consistent, and use CSV ▸ Repair ▸ Normalize Line Endings in Caxton, or dos2unix, to make it so.

Sources