# Vim Line Ending Issues
You open a file and see ^M at the end of every line, or Git complains about line endings. These issues stem from different line ending conventions across operating systems. Let me show you how to fix them.
Understanding Line Endings
Different operating systems use different characters for line endings:
| System | Characters | Hex | Display |
|---|---|---|---|
| Unix/Linux/macOS | LF | 0x0A | \n |
| Windows | CRLF | 0x0D 0x0A | \r\n |
| Old Mac (pre-OS X) | CR | 0x0D | \r |
Check Current File Format
Vim calls line endings "fileformat". Check the current setting:
:set fileformat?Returns unix, dos, or mac.
You can also see both the fileformat and encoding:
:set ff?Viewing ^M Characters
When you see ^M in Vim, those are carriage return characters (\r). They appear when a file with Windows line endings is opened as Unix format.
To see them explicitly:
:set listThis shows all special characters. $ marks line endings, and ^M shows carriage returns.
Hide them again:
:set nolistConvert Line Endings
Convert Windows (CRLF) to Unix (LF)
:set fileformat=unix
:wOr use the abbreviated form:
:set ff=unix
:wConvert Unix (LF) to Windows (CRLF)
:set fileformat=dos
:wConvert to Mac (CR only - rarely needed now)
:set fileformat=mac
:wRemove ^M Characters Manually
If the conversion doesn't work, remove them manually:
" Substitute all ^M characters
:%s/\r//gNote: Type ^M as Ctrl-V Ctrl-M, not as the literal characters ^ and M.
Or using the escape sequence:
:%s/\r\+$//gForce File Format on Open
Open a file with a specific format:
```vim " Open as Unix format :e ++ff=unix
" Open as DOS format :e ++ff=dos ```
This tells Vim how to interpret line endings regardless of detection.
Automatic Detection
Vim tries to detect the file format. Check what formats it considers:
:set fileformats?Default is usually unix,dos. This means Vim tries Unix first, then DOS.
For better detection, set:
set fileformats=unix,dos,macGit and Line Endings
Git has its own line ending handling. Configure .gitattributes:
``` # Auto-detect text files and normalize to LF * text=auto
# Files to always have LF *.sh text eol=lf *.py text eol=lf
# Files to always have CRLF *.bat text eol=crlf *.cmd text eol=crlf ```
In Git config:
```bash # Normalize to LF on commit, checkout as-is git config --global core.autocrlf input
# On Windows, checkout as CRLF, commit as LF git config --global core.autocrlf true ```
Batch Conversion from Shell
Convert multiple files:
```bash # Using dos2unix (install first) dos2unix *.txt
# Using sed sed -i 's/\r$//' *.txt
# Using tr tr -d '\r' < input.txt > output.txt ```
Preserve File Format
To keep the original file format when editing:
" Preserve file format
set preserveindentMixed Line Endings
Sometimes a file has mixed line endings. Find them:
```vim " Search for CR characters /\r
" Or show fileformat on each line :%!cat -A ```
Fix mixed endings by converting:
:set ff=unix
:wModeline for File Format
Add a modeline to files to ensure consistent handling:
# vim: set fileformat=unix :Or in comments:
<!-- vim: set fileformat=dos: -->Script to Fix Line Endings
Add this to your .vimrc:
```vim function! FixLineEndings() let l:ff = &fileformat if l:ff == 'dos' set fileformat=unix write echo 'Converted to Unix line endings' endif endfunction
command! FixLines call FixLineEndings() ```
Automatic Fix on Save
Auto-convert to Unix format for specific files:
autocmd BufWritePre *.sh,*.py,*.c,*.h set ff=unixDisplay Line Ending Info in Status Line
Show file format in your status line:
set statusline=%<%f\ %h%m%r%=%y%{&ff}\ %-14.(%l,%c%V%)\ %PThe %{&ff} shows the current file format.
Troubleshooting Common Issues
Git Shows File as Modified but No Changes
This is usually line ending conversion. View the actual changes:
git diff -w # Ignore whitespace
git diff --ignore-cr-at-eolFile Appears as One Long Line
The file might have Mac (CR only) line endings:
:e ++ff=mac
:set ff=unix
:wScripts Fail with /bin/bash^M: bad interpreter
The script has Windows line endings. Convert it:
:set ff=unix
:wOr from command line:
dos2unix script.shVim Changes Line Endings on Save
Vim preserves format by default. If it's changing, check:
:set fileformat?
:set fileformats?Make sure the format is detected correctly before saving.
Quick Reference
```vim " Check current format :set ff?
" Convert to Unix :set ff=unix
" Convert to Windows :set ff=dos
" Open with specific format :e ++ff=unix
" Remove ^M characters :%s/\r//g
" Show special characters :set list
" Hide special characters :set nolist ```
Line ending issues are straightforward once you understand the file format settings. The key is knowing how to check, convert, and prevent them in the future.