# Line endings: LF, CRLF and CR, and how this detector counts them

> What LF, CRLF and a lone CR are, why a stray carriage return breaks scripts and diffs, exactly what the detector counts and cannot see, and command-line and Git checks, with outputs from real files.

- Tool: [Line Ending Detector (LF vs CRLF)](https://toolsg.com/en/line-ending-detector)
- Language: en (available: en, zh, ms, ta)
- Last verified against official sources: 2026-10-20
- Source site: ToolSG — a planning guide, not official or financial advice. Cite the agencies listed under Sources.

## Key figures at a glance

| Fact | Value | Source |
| --- | --- | --- |
| LF (\n) | U+000A, used by Unix, Linux and macOS text files — POSIX defines a line as non-newline characters plus a terminating newline. | [The Open Group — POSIX definitions](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html) |
| CRLF (\r\n) | U+000D U+000A, the Windows convention — RFC 4180 specifies CRLF between CSV records. | [IETF — RFC 4180](https://www.rfc-editor.org/rfc/rfc4180.html) |
| What the detector counts | Line breaks, not lines — LF without a preceding CR, and CRLF. A lone CR is not counted. |  |
| Textarea behaviour | Typed text is always read back with LF only — A paste that replaces the whole box and the conversion buttons keep CRLF; any later typing drops it. |  |

## Fixing a script that fails on Linux with a CRLF problem

A shell script saved with Windows line endings often fails with a confusing 'not found' error.

1. **Confirm the line endings** — Run file script.sh, or paste the text here and press Analyze. Look for CRLF in the output.
2. **Convert to LF** — Press Convert to LF and use Copy or Download, or run sed -i 's/\r$//' script.sh in a terminal.
3. **Check the first line again** — The shebang line must end in a bare LF. Verify with cat -A script.sh: no ^M before the $.
4. **Stop it coming back** — Add a .gitattributes rule such as *.sh text eol=lf so Git writes LF in every checkout.

## Three kinds of line ending

| Name | Characters | Typical origin |
| --- | --- | --- |
| LF | `\n`, U+000A | Unix, Linux, macOS, most web and source files |
| CRLF | `\r\n`, U+000D U+000A | Windows text files, many network protocols and CSV per RFC 4180 |
| CR | `\r`, U+000D | classic Mac OS, now rare |

POSIX defines a *line* as "a sequence of zero or more non-newline characters plus a terminating newline character". So `wc -l` counts newlines, not visible lines: `one⏎two` with no final newline reports 1, and `one⏎two⏎` reports 2. An "incomplete line" is text at the end of a file with no terminating newline.

## What the detector reports

Paste text and press **Analyze**. It counts two things with regular expressions: an LF not preceded by a CR, and CRLF pairs. The panel shows the **total** (LF plus CRLF, which is the number of line breaks, one fewer than the number of lines if the text has no final newline), the LF count, the CRLF count, and a verdict: LF only, CRLF only, or Mixed (both present). If there are no breaks it says "No line breaks detected".

Verified on the real page:

| Pasted (replacing the box) | Result |
| --- | --- |
| `one\r\ntwo\r\nthree\r\n` | total 3, LF 0, CRLF 3, "CRLF (Windows)" |
| `one\ntwo\r\nthree\n` | total 3, LF 2, CRLF 1, "Mixed" |
| `one\ntwo\nthree\n` | total 3, LF 3, CRLF 0, "LF (Unix/Linux/macOS)" |
| `a\rb\rc` (CR only) | "No line breaks detected": a lone CR is not counted |

**Convert to LF** changes CRLF and lone CR to LF. **Convert to CRLF** first normalises everything to LF and then writes CRLF, so mixed text becomes consistent. Copy and Download use that converted text; the download is called `text-with-line-endings.txt`.

## What the page cannot see

A browser textarea does not hold your characters verbatim. The HTML standard says its value getter returns the text "with newlines normalized", which means CRLF and CR read back as LF. This page works around that for two cases only: pasting that replaces the entire contents of the box, and the text produced by its own conversion buttons. In both cases the original CR characters are kept alongside the textarea and used for analysis, copying and downloading.

Everything else is LF-only:

- Text you type, or paste into the middle of existing text, is read back with LF only; so it is reported as LF, even if the pasted text had CRLF.
- Once you type anything after a paste or a conversion, the CR characters are gone and the page works on the LF-only text.
- Lone CR is never counted, so an old Mac-style file reports "No line breaks detected" until you convert it.

For files on disk, a terminal gives the truthful answer.

## Checking real files

Outputs from files created with `printf`:

| File contents | `file` says | `od -c` shows |
| --- | --- | --- |
| `one\ntwo\nthree\n` | ASCII text | `\n` after each word |
| `one\r\ntwo\r\nthree\r\n` | ASCII text, with CRLF line terminators | `\r \n` pairs |
| `one\rtwo\rthree\r` | ASCII text, with CR line terminators | `\r` only |
| `one\ntwo\r\nthree\n` | ASCII text, with CRLF, LF line terminators | both |

`wc -l` printed 3, 3, 0 and 3 for those four files. The CR-only file has zero newlines, so tools that read line by line see it as one long line. `cat -A file` shows a `^M` before the `$` on CRLF lines, and `grep -c $'\r' file` counts lines containing a CR. In a Git repository, `git ls-files --eol` lists the line ending recorded in the index (`i/`) and in the working tree (`w/`): it printed `i/lf`, `i/crlf`, `i/mixed`, and `i/-text` for the CR-only file, which Git does not treat as text.

## Why it matters

A script that starts `#!/bin/sh` followed by a carriage return names the interpreter `/bin/sh\r`. Run directly in a bash shell, it failed with "cannot execute: required file not found", while `sh script.sh` ran but treats every line as ending in a stray CR. After `sed -i 's/\r$//' script.sh` the same script ran and printed `hi`. Other effects: whole-file diffs when one editor rewrites every line ending, failing string comparisons, and a `\r` that survives into the last field of CSV or config values.

## Git and teams

Git can normalise line endings, but only if it is told to. Setting `text=auto` in `.gitattributes` makes Git decide whether a file is text and normalise CRLF to LF in the index; `eol=lf` or `eol=crlf` fixes what is written to the working tree; without either, `core.autocrlf` decides. A common starting rule is `* text=auto`, then `git add --renormalize .` once to convert existing files. The Git documentation describes the renormalising procedure in full.

> **Tip:** Prefer the project-level `.gitattributes` over each developer's `core.autocrlf`, so the rule travels with the repository.

## Common mistakes

- Reading "Total" as the number of lines. It counts line breaks.
- Pasting into the middle of existing text and trusting an "LF" verdict for CRLF input.
- Editing after converting to CRLF and then downloading; typing discards the CRs.
- Converting binary files, which may legitimately contain bytes that look like CR or LF.
- Forgetting the final newline: POSIX tools treat the last unterminated text as an incomplete line.

## Related tools

Find other invisible characters with the [hidden character cleaner](https://toolsg.com/en/hidden-character-cleaner), compare two versions with the [text diff](https://toolsg.com/en/text-diff), or see the bytes of a string with the [text to hex converter](https://toolsg.com/en/text-to-hex).

## Frequently asked questions

**What is the difference between LF and CRLF line endings?**

LF (Line Feed) is a single character (\n, ASCII 10) used by Unix, Linux, and macOS systems for line endings. CRLF (Carriage Return + Line Feed) is a two-character sequence (\r\n, ASCII 13 + 10) used by Windows and DOS systems. The difference originates from historical typewriter and teletype mechanisms where carriage return moved the print head to the start of the line, and line feed advanced the paper to the next line. Modern operating systems maintain these conventions for backward compatibility.

**Why do line endings matter in programming and text files?**

Line endings matter because incorrect formats can cause multiple issues: shell scripts may fail to execute, version control systems may show files as changed when only line endings differ, text editors may display files incorrectly, compilers may produce errors, and cross-platform collaboration can become problematic. Consistent line endings ensure reliable behavior across different systems and tools.

**How can I detect what line endings my file uses?**

Paste your file contents into this tool and click "Analyze Line Endings." The tool will show you detailed statistics including the number of LF lines, CRLF lines, whether you have mixed line endings, and the dominant format. You can also use text editors like VS Code (shows "LF" or "CRLF" in the status bar), Notepad++ (View → Show Symbol → Show End of Line), or command-line tools like "file" on Unix systems.

**Should I use LF or CRLF for my project?**

For most modern development, LF (Unix-style) is recommended even on Windows, as most development tools support it. Use LF for source code, shell scripts, configuration files, and general text files. Use CRLF only for files specifically needed on Windows (like .bat or .cmd files). The most important aspect is consistency - pick one format and use it throughout your project.

**What are mixed line endings and why are they problematic?**

Mixed line endings occur when a single file contains both LF and CRLF line endings. This typically happens when multiple people edit a file using different text editors with different settings, or when copying and pasting code from different sources. Mixed line endings can cause unpredictable behavior, make diffs hard to read, trigger linting errors, and cause scripts to fail. Always standardize to a single line ending format.

**How do I fix line ending issues in Git?**

Configure Git to automatically handle line endings by creating a .gitattributes file in your repository with "* text=auto". This tells Git to normalize line endings to LF in the repository and convert them to the platform-appropriate format on checkout. You can also use "git config --global core.autocrlf" (set to "true" on Windows, "input" on Mac/Linux). For existing files with wrong line endings, use this tool to convert them, then commit the changes.

**Can wrong line endings break my shell scripts?**

Yes, shell scripts with CRLF line endings will typically fail to execute on Unix/Linux systems. The shell interpreter sees the carriage return (\r) as part of the command, causing errors like "command not found" or "bad interpreter." If you edit shell scripts on Windows, always ensure they use LF line endings before deploying them to Unix/Linux servers. This tool can convert CRLF to LF instantly.

**How can I prevent line ending problems in my team?**

Establish a team convention (usually LF for modern development), create a .gitattributes file to enforce it, configure your IDE/editor to use consistent line endings, add line ending checks to your CI/CD pipeline, document the standard in your project README, and use pre-commit hooks to validate line endings before commits. This tool can help team members verify and fix line endings before pushing code.

**Does this tool send my text to a server?**

No, all line ending detection and conversion happens entirely in your web browser using JavaScript. Your text never leaves your device or gets sent to any server. This makes the tool completely safe for analyzing sensitive code, configuration files, or proprietary scripts. The tool works offline after the initial page load.

**What is the file size difference between LF and CRLF?**

CRLF line endings use two bytes per line ending (\r\n) while LF uses only one byte (\n). For a file with many lines, this can result in a noticeable size difference. For example, a file with 1,000 lines will be approximately 1KB larger with CRLF compared to LF. While usually not significant for source code, it matters for very large files or when optimizing bandwidth and storage.

**Can I use this tool for large files?**

Yes, this tool can handle text files of any size since all processing is done locally in your browser. However, extremely large files (several megabytes or more) may take a moment to process depending on your computer's performance. For very large files, you might want to use command-line tools like dos2unix or unix2dos which are optimized for batch processing.

**How do line endings affect Docker containers?**

When building Docker containers, shell scripts and configuration files must use LF (Unix) line endings, even if you're developing on Windows. If you copy a shell script with CRLF line endings into a Linux container, the script will fail to execute. Always verify that your Dockerfile, shell scripts, and configuration files use LF before building container images. This tool can quickly convert Windows-edited files to Unix format.


## Sources

- [The Open Group — POSIX.1-2017 Base Definitions, chapter 3](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html) — Definitions of Line (3.206), Incomplete Line (3.195) and Newline Character (3.243).
- [IETF — RFC 4180, Common Format and MIME Type for CSV Files](https://www.rfc-editor.org/rfc/rfc4180.html)
- [Git documentation — gitattributes](https://git-scm.com/docs/gitattributes) — text, eol and text=auto; core.autocrlf.
- [WHATWG HTML Standard — The textarea element](https://html.spec.whatwg.org/multipage/form-elements.html) — The value getter returns the API value, with newlines normalised to LF.
