改行コード(CR/LF)の調整
nkfコマンドはUnix形式(LF, 0A)とWindows形式(CRLF, 0D0A)の改行コードを相互に変換する。CRLF形式のシェルスクリプトが直接実行できない主な原因は、インタプリタ指定行(シバン行)の末尾にCRが付くことである。改行コードはcat -Aコマンドで確認できる。Ubuntu 24.04 LTSではaptコマンドでnkfをインストールできる。
改行コードは、テキストファイルで行の終わりを示す制御文字である。Unix/Linux系OSでは LF (Line Feed、16進数で 0A) を用いる。Windowsでは CRLF (Carriage Return + Line Feed、16進数で 0D0A) を用いる。OS間でテキストファイルをやり取りすると、この違いが問題になることがある。特にシェルスクリプトや設定ファイルでは、CRLF形式のファイルが正しく解釈されず、エラーの原因になる。
nkf(Network Kanji Filter)は日本語の文字コード変換ツールであり、改行コードの変換にも使用できる。Unix形式の改行コード (LF) とWindows形式の改行コード (CRLF) の相互変換を行える。
Ubuntu での nkf のインストール
# パッケージリストの情報を更新
sudo apt update
sudo apt -y install nkf
Ubuntu では apt パッケージマネージャーで nkf をインストールする。上記のコマンドを実行する。Ubuntu 24.04 LTS では、nkf のバージョンは 2.1.5 である。
Unix 形式の改行コード (LF) から Windows 形式の改行コード (CRLF) への変換
nkf -Lw hoge.sh > hoge2.sh
-Lw オプションは、改行コードをWindows形式 (CRLF) に変換して出力することを指定する。
◇ 変換元のシェルスクリプト hoge.sh を次の内容で作成する。改行コードはLF形式とする。
#!/bin/bash
echo "Hello, world!"
◇ LF形式で作成した hoge.sh をWindows形式の改行コード (CRLF) に変換すると、シェルスクリプトとして実行できなくなる。CRLF形式では行末にLFだけでなくCR(\r)も付くため、インタプリタ指定行 #!/bin/bash の末尾にCRが付き、シェルが /bin/bash というインタプリタを見つけられなくなるためである。
* Ubuntu での実行例
上図は実行例の画面である。同じ操作をコマンドと出力で示す。ファイルの内容確認には cat -A コマンドを用いる。cat -A はLFを $、CRを ^M として表示する。
# 変換前の hoge.sh (LF形式) の内容を確認する
$ cat -A hoge.sh
#!/bin/bash$
echo "Hello, world!"$
# nkfでCRLF形式に変換する
$ nkf -Lw hoge.sh > hoge2.sh
# 変換後の hoge2.sh (CRLF形式) の内容を確認する。行末に ^M が付いている。
$ cat -A hoge2.sh
#!/bin/bash^M$
echo "Hello, world!"^M$
# CRLF形式のシェルスクリプトを直接実行するとエラーになる
$ chmod +x hoge2.sh
$ ./hoge2.sh
bash: ./hoge2.sh: cannot execute: required file not found
インタプリタ指定行はカーネルが解釈するため、このエラーは ./hoge2.sh のようにスクリプトを直接実行したときに発生する。エラーメッセージは bash のバージョンで異なり、Ubuntu 24.04 LTS の bash 5.2 では上記のように表示される。bash 5.0 以前では /bin/bash^M: bad interpreter: No such file or directory と表示される。
Windows 形式の改行コード (CRLF) から Unix 形式の改行コード (LF) への変換
nkf -Lu hoge2.sh > hoge3.sh
-Lu オプションは、改行コードをUnix形式 (LF) に変換して出力することを指定する。
* Ubuntu での実行例
上図は実行例の画面である。同じ操作をコマンドと出力で示す。ファイルの内容確認には cat -A コマンドを用いる。cat -A はLFを $、CRを ^M として表示する。
# 変換前の hoge2.sh (CRLF形式) の内容を確認する
$ cat -A hoge2.sh
#!/bin/bash^M$
echo "Hello, world!"^M$
# nkfでLF形式に変換する
$ nkf -Lu hoge2.sh > hoge3.sh
# 変換後の hoge3.sh (LF形式) の内容を確認する。行末の ^M が取り除かれている。
$ cat -A hoge3.sh
#!/bin/bash$
echo "Hello, world!"$
# LF形式に変換したシェルスクリプトは実行できる
$ chmod +x hoge3.sh
$ ./hoge3.sh
Hello, world!