Convert line endings between CRLF and LF
Strip or insert carriage returns to switch a file between Windows (CRLF, \r\n) and Unix (LF, \n) line endings.
How to convert line endings between crlf and lf in each shell
tr -d "\r" < file.txt > file.unix.txt`tr -d` strips bytes — fast, single-pass, no regex overhead. For in-place edit: `sed -i "s/\r$//" file.txt` (GNU sed; BSD/macOS needs `sed -i ""`). The canonical tools `dos2unix` and `unix2dos` (`apt install dos2unix` / `brew install dos2unix`) handle in-place edits, BOM preservation, and binary detection — prefer them over hand-rolled `tr`/`sed` for production scripts.
tr -d "\r" < file.txt > file.unix.txtSame external tools as bash. Zsh-native: `<file.txt:gs/$\r//` — the `gs` parameter expansion flag does in-string global substitution.
tr -d "\r" < file.txt > file.unix.txtSame external tools. Fish string builtin: `string replace -r "\r" "" < file.txt`.
(Get-Content file.txt -Raw) -replace "`r`n", "`n" | Set-Content file.unix.txt -NoNewline`-Raw` reads the whole file as one string (preserves original endings); `-replace` uses .NET regex (backtick-r-backtick-n = CRLF). `Set-Content -NoNewline` prevents pwsh from APPENDING a fresh CRLF/LF on Windows pwsh 5.1 (UTF-16 LE default with BOM) — explicitly pass `-Encoding utf8NoBOM` on pwsh 5.1 to avoid the BOM altogether. Reverse direction: `-replace "`n", "`r`n"` (must NOT match existing CRLF first — do a `-replace "`r`n","`n"` then add CRLF).
powershell -NoProfile -Command "(Get-Content file.txt -Raw) -replace \"`r`n\", \"`n\" | Set-Content file.unix.txt -NoNewline"No native cmd line-ending converter. Shell out to pwsh (above) or install dos2unix via Git for Windows / WSL. Hack: `type file.txt | findstr /v "^$" > file.txt.tmp` does NOT strip CR — `findstr` works on logical lines regardless of line ending. Don't.
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- Detect first, convert second: `file file.txt` reports "ASCII text, with CRLF line terminators" on a CRLF file, plain "ASCII text" on a LF file. `cat -A file.txt` shows `$` at LF and `^M$` at CRLF. On Windows, `Get-Content file.txt | Format-Hex | Select-Object -First 3` shows the byte sequences. Always confirm the actual content before reaching for a converter — repeated conversions on the same file can corrupt.
- Binary files MUST be skipped — `tr -d "\r"` on a `.png` corrupts every byte 0x0D in the image. `dos2unix` auto-detects binaries (`file --mime` check) and refuses; `-f` forces. The classic disaster: running `dos2unix -R .` (recursive) on a checkout containing `.pdf` and `.png` files. Use `-ic` (info-check) first, OR filter with `find . -name "*.txt" -o -name "*.sh"` before processing.
- CSV files with CRLF inside QUOTED fields (RFC 4180) are NOT plain CRLF line endings — naive `tr -d "\r"` corrupts the data structure. Use a CSV parser (`csvkit`, pwsh `Import-Csv`) rather than line-ending tools when the format matters.
- Git can normalise on commit via `.gitattributes` (`* text=auto eol=lf`) and `core.autocrlf` — the canonical fix for "my IDE saves CRLF but my Linux server needs LF". Set per-repo with `git config core.autocrlf input` (Linux/macOS) or `git config core.autocrlf true` (Windows). Then `git add --renormalize .` rewrites the working tree.
Related commands
Related tasks
- Find and replace text in files— Substitute one string for another inside a file (or every file in a tree), in place.
- Encode a string to base64— Convert a string (or file) to its base64 representation — for HTTP basic auth headers, JWT payloads, embedded credentials in YAML, or any text-only transport of binary.