はじめに
Shift_JIS,CRLFへの文字コード・改行コード変換(ついでに確認も)するために作ったシェルをまとめておきます。
ピンポイントで求めてる方がいれば、かなり時間短縮できるかと・・・!
(逆にUTF-8へ変換したい場合やLFに変換したい場合もちょこっと弄ればできるはずです。)
※前提としてnkfコマンドを活用しているので、事前にインストールしておいてください。
①ディレクトリ以下のファイルをすべてShift_JIS,CRLFに変換する
# ディレクトリ以下全て変換
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変換する
ディレクトリ以下でじぶんの編集したソースだけ変換したい!みたいな場合は以下を実行!
# 対象のファイルのみ変換する
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)
--
ソース的には①をちょこっと弄っただけ。
③ディレクトリ以下のファイルすべての文字コード、改行コードを確認する※シェル不要
$ find . -type f | xargs nkf --guess | column -s: -t
あとは変換漏れを確認するためにShift_JISを除いて出力させるのもありですね◎
$ find . -type f | xargs nkf --guess | column -s: -t | grep -v "Shift_JIS"
④対象のファイルのみ文字コード、改行コードを確認する
# 対象のファイルのみ確認する
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です
終わり!
追記 CRLFからLFに一括変換
最近はLFにするケースの方が多いと思うので追記します。
※変換する前に一度echoで対象ファイルがあっているか確認することをお奨めします。
# ディレクトリ以下全て変換
echo 開始!
# 対象のディレクトリ(/は不要)
path="."
# 出力された全ファイルをfile_pathsに代入
# (補足)findで指定したフォルダ以下のファイルを出力。sedで重複するパスの部分を除去。
file_paths=`find $path* -type f | sed 's/^'$path'//' `
for file_path in $file_paths;
do
# ここで絶対パスにしてる。
file=$path$file_path
# ファイルの存在チェック(パス)
if [ -e $file ]; then
# 文字コードのチェック ※ UTF-8の場合はUTF-8と代入される。
character_code=`nkf -g $file`
echo $file
echo 変換前`nkf --guess $file`
# LF変換
nkf -Lu --overwrite $file
# CRLF変換
# nkf -Lw --overwrite $file
echo 変換後`nkf --guess $file`
echo --
continue
fi
done
echo 終わり!
最後に
書いてるうちに、条件分岐こっちの方がシンプルじゃん!とか、
変数内に半角スペースあるとエラるじゃん!みたいな気づきもあって、
定期的にアウトプットする重要性を再認識しました。
参考になる記事
新人さんに知ってほしい「文字コードのお話」
【 nkf 】コマンド――文字コードと改行コードを変換する
シェルスクリプトの条件評価ではまりやすいところ
シェルスクリプトに挑戦しよう(15)繰り返し処理の中断
シェルスクリプト(bash)のif文とtestコマンド([])自分メモ
bashでファイルやディレクトリの存在確認方法まとめ
bash 配列まとめ
findコマンドの使い方