問題
Linux 環境執行一些腳本出錯,查找原因,發現是文件在Windows環境修改並上傳,格式被轉換為MS-Dos格式(換行符不同),這樣的文件在Linux中運行會出錯(shell 解釋器把換行符作為一個命令的提交)。
背景
很久以前,老式的電傳打字機使用兩個字符來另起新行。回車符(CR)把滑動架移回行首 ,換行符(LF)把紙上移一行 。
當計算機問世以后,存儲器曾經非常昂貴。有些人就認定沒必要用兩個字符來表示行尾。
UNIX 用 <LF> 一個字符來表示行尾。
Apple 的MacOS 9 及以前用 <CR> ,MacOS 10跟Unix一樣。
MS-DOS (以及Windows) 沿用老式的<CR><LF>,即敲一下回車鍵,相當於同時執行了 "回車+換行"。
總結一下:
系統 | 中文描述 | 英文描述 | 簡寫 | 轉義符 |
---|---|---|---|---|
Windows | 回車換行 | Carriage Return and Line Feed | CRLF | \n\r |
Unix/Linux/Mac OS | 換行 | Line Feed | LF | \n |
如果你把一個文件從一種系統移到另一種系統,那么你就有換行符方面的麻煩。
Windows10的記事本(notepad)能夠自動識別Linux文件,但是在Linux中查看MS-DOS格式文件會發現每一行的末尾有個 ^M 字符。(^M 就是 <CR>)。
單個文件解決辦法
Linux 環境下 vim 直接編輯修改文件。
:set fileformat=unix
或者
:set ff=unix
保存退出就解決了。
批量文件解決方案一
這是通用方案,核心邏輯是
- 找出文件:用
file
命令查看文件是否有特殊換行符 - 修改文件:
dos2unix
命令直接改。(也可以vi 文件修改,后面在舉例)
具體例子
1. 檢查文件
$ file ./test.yml
./test.yml: ASCII text, with CRLF line terminators
輸出中看到了CRLF
,這是Dos文件格式的標志。
2. 下一步,文件格式轉換
$ dos2unix ./test.yml
dos2unix: converting file ./test.yml to Unix format ...
3. 檢查文件是否真的修改了格式
$ file ./test.yml
./test.yml: ASCII text
發現沒有CRLF 標志,修改完成。
4. 把上面的命令合並,查找並修改Dos格式文件
$ find . -type f -exec file {} \; | grep CRLF | awk -F: '{print $1}' | xargs dos2unix
dos2unix: converting file ./ansible/README.md to Unix format ...
...
or
$ find . -type f -exec file {} \; | grep CRLF | cut -d : -f 1 | xargs dos2unix
批量文件解決方案二
從 7.1 版本后,dos2unix 有 -i
, --info
參數,能夠直接獲取文件換行符的信息,我們能直接用這個命令來查找和替換。-ic
參數表示只是打印需要轉換的文件。
(MacOS 通過brew 可以安裝 dos2unix version 7.4,而centos 7 和 ubuntu 16 默認只能安裝版本6.0,更高版本需要自己單獨下載安裝包。)
$ dos2unix -i ./roy_test.yml
11 0 0 no_bom text ./roy_test.yml
$ dos2unix -ic ./roy_test.yml
./roy_test.yml
上面的輸出數字 11 表示有11個dos換行符。
查找並修改dos文件:
$ find . -type f -exec dos2unix -ic {} \; | xargs dos2unix
dos2unix: converting file ./bin/Readme.txt to Unix format...
...
如果文件數量大,用xargs 替換 exec 更有效率,所以更好的命令是
$ find . -type f | xargs dos2unix -ic | xargs dos2unix
Windows開發中避免換行問題
使用編輯器Visual Studio Code
這個工具的右下角的文件格式確保是LF。如果不是,就點擊重新選擇。

gitbash 中設置默認檢入檢出換行符為linux(\n)風格
(為了團隊更好的協作)
開啟自動換行
$ git config --global core.autocrlf true
git config --global core.autocrlf true 簽出時將換行符轉換成CRLF,簽入時轉換回 LF
git config --global core.autocrlf input 簽出時不轉換換行符,簽入時轉換回 LF
git config --global core.autocrlf false 簽出簽入均不轉換
開啟安全換行
$ git config --global core.safecrlf true
解釋:
如果你把換行符搞亂了,在一個文件中既包含windows風格的換行符也包含unix風格換行符,那么 safecrlf 就可以發揮作用了:
git config --global core.safecrlf true 拒絕提交包含混合換行符的文件
git config --global core.safecrlf false 允許提交包含混合換行符的文件
git config --global core.safecrlf warn 提交包含混合換行符的文件時候給出警示
參考文檔
作者:華陽_3bcf
鏈接:https://www.jianshu.com/p/fe8ec5f5792d
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。