Windows (CRLF, \r\n) 與 Linux (LF, \n) 換行格式差異導致 ^M 字元殘留,影響腳本執行、版本控制、編譯建構。本文提供多種移除方案。
cat -A file.txt # 顯示 ^M$ (CRLF) 或 $ (LF)
od -c file.txt | head # 八進制檢視 \r \n
file file.txt # 輸出 "ASCII text, with CRLF line terminators"
# 安裝
yum install -y dos2unix # RHEL/CentOS
apt install -y dos2unix # Debian/Ubuntu
# 轉換
dos2unix file.txt # CRLF → LF (原地修改)
dos2unix -n file.txt new.txt # 建立新檔
dos2unix -k file.txt # 保留時間戳
dos2unix -r . # 遞迴處理目錄
# 反向轉換
unix2dos file.txt # LF → CRLF
# 原地修改 (GNU sed)
sed -i 's/\r$//' file.txt
# 建立新檔
sed 's/\r$//' file.txt > file.unix.txt
# 處理多檔
find . -name "*.sh" -exec sed -i 's/\r$//' {} \;
注意:\r 在 bash $'' 字串中可寫作 $'\r',或在 vi 中 Ctrl+V Ctrl+M 輸入實際字元。
# 在 vim 中
:set ff=unix # 設定檔案格式為 Unix (LF)
:w # 存檔即轉換
# 或命令列模式
:%s/\r//g # 全域移除 \r
tr -d '\r' < file.txt > file.unix.txt
# 或原地 (需暫存)
tr -d '\r' < file.txt > file.tmp && mv file.tmp file.txt
python3 -c "import sys; sys.stdout.write(sys.stdin.read().replace('\r\n', '\n'))" < file.txt > new.txt
perl -pi -e 's/\r\n/\n/g' file.txt
# 全域設定:簽出時轉 LF,提交時保持 LF
git config --global core.autocrlf input
# 專案級 .gitattributes (推薦,強制規範)
echo "* text=auto eol=lf" > .gitattributes
echo "*.sh text eol=lf" >> .gitattributes
echo "*.bat text eol=crlf" >> .gitattributes
"files.eol": "\n"set fileformat=unix、set fileformats=unix,dos
#!/bin/bash
# fix_line_endings.sh: 遞迴轉換專案內所有文字檔為 LF
find . -type f \( -name "*.sh" -o -name "*.py" -o -name "*.txt" -o -name "*.md" -o -name "*.conf" \) \
-exec file {} \; | grep "CRLF" | cut -d: -f1 | xargs -r dos2unix
echo "Line endings normalized to LF"
建立「提交前檢查」 (pre-commit hook) 強制 LF 格式,配合編輯器預設 Unix 換行,可從源頭杜絕 ^M 污染。