LoginSignup
3
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-01-31

はじめに

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 終わり!

出力結果

gitbash
$ 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 終わり!

出力結果

gitbash
$ 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"

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

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 終わり!

出力結果

gitbash
$ 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除いた漏れ分のみ出力させるなんかもありかも。ってことで追記。

check.sh
# 対象のファイルのみ確認する
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 終わり!

出力結果

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

追記 CRLFからLFに一括変換

最近はLFにするケースの方が多いと思うので追記します。
※変換する前に一度echoで対象ファイルがあっているか確認することをお奨めします。

check.sh
# ディレクトリ以下全て変換
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コマンドの使い方

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2