Shift_JIS,CRLFに一括変換・確認するシェル

はじめに

Shift_JIS,CRLFへの文字コード・改行コード変換(ついでに確認も)するために作ったシェルをまとめておきます。
ピンポイントで求めてる方がいれば、かなり時間短縮できるかと・・・!
(逆にUTF-8へ変換したい場合やLFに変換したい場合もちょこっと弄ればできるはずです。)

※前提としてnkfコマンドを活用しているので、事前にインストールしておいてください。

①ディレクトリ以下のファイルをすべてShift_JIS,CRLFに変換する

conversion.sh

# ディレクトリ以下全て変換
echo 開始!

# 対象のディレクトリ
path="/c/development"

# 出力された全ファイルをfile_pathsに代入
file_paths=`find $path* -type f | sed 's/^'$path'//' `

for file_path in $file_paths;
do
# ここで絶対パスにしてる。
file=$path$file_path

# ファイルの存在チェック(パス)
if [ -e $file ]; then

# 文字コードのチェック
character_code=`nkf -g $file`

# BINARYファイルはスキップ
if [ ${character_code} = "BINARY" ] ; then
continue
fi

# Shift_JIS以外のファイルをShift_JIS,CRLFに変換(後続の処理はスキップ)
if [ ! ${character_code} = "Shift_JIS" ] ; then
echo $file
echo 変換前`nkf --guess $file`
nkf -sc --overwrite $file
echo 変換後`nkf --guess $file`
echo --
continue
fi

## ここからShift_JISファイルの改行コード変換処理

# 改行コードのチェック(sedコマンドで文字コード部分だけ取り出し)
lf_code=`nkf --guess $file | sed -e "s/^.*(\(.*\)).*$/\1/" `

# CRLF以外(LFもしくはMIXED NL)ならShift_JIS,CRLFに変更
if [ ! "${lf_code}" = "CRLF" ] ; then
# if [ "${lf_code}" = "LF" ] || [ "${lf_code}" = "MIXED NL" ] ; then # こっちでもOK
echo $file
echo 変換前`nkf --guess $file`
nkf -sc --overwrite $file
echo 変換後`nkf --guess $file`
echo --
fi

fi
done

echo 終わり!

出力結果

$ sh conversion.sh
/c/development/hoge.java
変換前UTF-8 (LF)
変換後Shift_JIS (CRLF)
--
/c/development/hoge3.java
変換前Shift_JIS (LF)
変換後Shift_JIS (CRLF)
--

注意点
・CP932はShift_JISにならずCP932のままになるみたいです。ASCIIについても同じまま(BINARYと同じくスキップしてもいいかも)。
MIXED NLで半角スペースが含まれる可能性があるので条件文の中のlf_codeはダブルクォーテーションで囲んでる。
・Shift_JISファイルの改行コード変換でsオプションでShift_JISと明示せずに変換するとISO-2022-JPになる。

nkf -sc --overwrite $fileを全ファイルに実行するのもありっちゃありなんですが、
そうすると既存のShift_JIS,CRLFファイルなどターミナルに出力されて見にくいので条件分岐で絞り込みました。

②対象のファイルのみShift_JIS,CRLF変換する

ディレクトリ以下でじぶんの編集したソースだけ変換したい!みたいな場合は以下を実行!

conversion_narrow.sh

# 対象のファイルのみ変換する
echo 開始!

# 対象のディレクトリ
path="/c/development/"

# 対象のファイル(git statusとかで出した対象のファイルをここに書く。)
file_paths=(
"product1/aaa.java"
"product1/bbb.java"
"product2/ccc.java"
)

for file_path in ${file_paths[@]};
do
file=$path$file_path

# ファイルの存在チェック(パス)
if [ -e $file ]; then

# 文字コードのチェック
character_code=`nkf -g $file`

# BINARYファイルはスキップ
if [ ${character_code} = "BINARY" ] ; then
continue
fi

#Shift_JIS以外ならShift_JIS,CRLFに変換(後続の処理はスキップ)
if [ ! ${character_code} = "Shift_JIS" ] ; then
echo $file
echo 変換前`nkf --guess $file`
nkf -sc --overwrite $file
echo 変換後`nkf --guess $file`
echo --
continue
fi

#改行コードのチェック(sedコマンドで文字コード部分だけ取り出し)
lf_code=`nkf --guess $file | sed -e "s/^.*(\(.*\)).*$/\1/" `

# CRLF以外(LFもしくはMIXED NL)ならShift_JIS,CRLFに変更
if [ ! "${lf_code}" = "CRLF" ] ; then
echo $file
echo 変換前`nkf --guess $file`
nkf -sc --overwrite $file
echo 変換後`nkf --guess $file`
echo --
fi

fi
done

echo 終わり!

出力結果

$ sh conversion.sh
/c/development/product1/aaa.java
変換前UTF-8 (LF)
変換後Shift_JIS (CRLF)
--
/c/development/product2/ccc.java
変換前Shift_JIS (LF)
変換後Shift_JIS (CRLF)
--

ソース的には①をちょこっと弄っただけ。

③ディレクトリ以下のファイルすべての文字コード、改行コードを確認する※シェル不要

以下をターミナルで実行するだけでOK

$ find . -type f | xargs nkf --guess | column -s: -t

変換漏れを確認するためにShift_JISを除いて出力させるのもありですね◎

$ find . -type f | xargs nkf --guess | column -s: -t | grep -v "Shift_JIS"

④対象のファイルのみ文字コード、改行コードを確認する

check.sh

# 対象のファイルのみ確認する
echo 開始!

# 対象のディレクトリ
path="/c/development/"

# 対象のファイル
file_paths=(
"product1/aaa.java"
"product1/bbb.java"
"product2/ccc.java"
)

for file_path in ${file_paths[@]}; do
file=$path$file_path
echo $file
nkf --guess $file | column -s: -t
echo --
done

echo 終わり!

出力結果

$ sh check.sh
/c/development/product1/aaa.java
Shift_JIS (CRLF)
--
/c/development/product1/bbb.java
Shift_JIS (CRLF)
--
/c/development/product2/ccc.java
Shift_JIS (CRLF)
--

おまけ ④からShift_JIS,CRLFを除いた対象ファイルを出力

Shift_JIS,CRLF除いた漏れ分のみ出力させるなんかもありかも。ってことで追記。

# 対象のファイルのみ確認する
echo 開始!

# 対象のディレクトリ
path="/c/development/"

# 対象のファイル
file_paths=(
"product1/aaa.java"
"product1/bbb.java"
"product2/ccc.java"
)

# 確認対象のファイル数をカウント
total="${#file_paths[@]}"

# Shift_JIS,CRLFになっていないファイルをカウントするための変数
count=0

for file_path in ${file_paths[@]}; do
file=$path$file_path
check=`nkf --guess $file`
if [ ! "${check}" = "Shift_JIS (CRLF)" ] ; then
echo $file
nkf --guess $file | column -s: -t
let count++
echo --
fi
done

echo "Shift_JIS,CRLFになっていないファイルは$count/$totalです"

echo 終わり!

出力結果

$ sh check.sh
/c/development/product1/aaa.java
Shift_JIS (LF)
--
Shift_JIS,CRLFになっていないファイルは1/3です
終わり!

最後に

書いてるうちに、条件分岐こっちの方がシンプルじゃん!とか、
変数内に半角スペースあるとエラるじゃん!みたいな気づきもあって、
定期的にアウトプットする重要性を再認識しました。

参考になる記事

新人さんに知ってほしい「文字コードのお話」
【 nkf 】コマンド――文字コードと改行コードを変換する
シェルスクリプトの条件評価ではまりやすいところ
シェルスクリプトに挑戦しよう(15)繰り返し処理の中断
シェルスクリプト(bash)のif文とtestコマンド([])自分メモ
bashでファイルやディレクトリの存在確認方法まとめ
bash 配列まとめ
findコマンドの使い方

コメントを残す