fork download
  1. import sys
  2. import os
  3. import glob
  4. #文字列変換クラス
  5. class ConvString():
  6. def __init__(self):
  7. self.err_count = 0
  8. # 文字コードをUTF-8からSJISに変換する
  9. # 戻り値 None :全文字がUTF8からSJISに変換完了
  10. # 戻り値 None以外 :UTF8からSJISに変換できない文字があるため、変換不能文字を(N)に置換
  11. def convert(self,str_in):
  12. #1文字ずつ文字コードを変換する。
  13. out_str = ""
  14. err_flag = False
  15. for i in range(len(str_in)):
  16. try:
  17. en = str_in[i].encode("cp932")
  18. cv = en.decode("cp932")
  19. except Exception as e:
  20. #変換エラー
  21. self.err_count += 1
  22. err_flag = True
  23. cvt = "(" + str(self.err_count) + ")"
  24. out_str += cvt
  25. else:
  26. out_str += str_in[i]
  27.  
  28. if err_flag == False:
  29. return None
  30. else:
  31. return out_str
  32.  
  33. #ログファイルオープン
  34. def log_open():
  35. global log_fp
  36. log_fp = open("./log.txt","w",encoding="utf8")
  37.  
  38. #画面とログファイルの両方に出力する
  39. def log_print(msg):
  40. global log_fp
  41. print(msg)
  42. log_fp.write(msg+"\n")
  43.  
  44. #ログファイルクローズ
  45. def log_close():
  46. global log_fp
  47. log_fp.close()
  48.  
  49.  
  50. args = sys.argv
  51. if len(args) != 3:
  52. print("指定されたディレクトリ下のファイルについて再帰的に以下の処理行う")
  53. print(f"{args[0]} P1 P2")
  54. print("P1:機能コード")
  55. print(" list :SJISに変換できないファイルの一覧を出力する")
  56. print(" exec :SJISに変換できないファイルをSJISに変換可能なファイルにリネームする")
  57. print("P2:ディレクトリ名")
  58. sys.exit(10)
  59.  
  60. #機能コードチェック
  61. func = 0
  62. if args[1] == "list":
  63. func = 1
  64. elif args[1] == "exec":
  65. func = 2
  66. else:
  67. print("機能コードエラー")
  68. sys.exit(10)
  69. #ディレクトリ名チェック
  70. adir = os.path.abspath(args[2])
  71. if os.path.isdir(adir) == False:
  72. print(f"<{args[2]}> そのようなディレクトリはありません")
  73. sys.exit(10)
  74.  
  75. file_count = 0
  76. ren_count = 0
  77. err_count = 0
  78. err_files = []
  79. log_fp = None
  80. log_open()
  81. #文字列変換クラス生成
  82. conv = ConvString()
  83. #指定フォルダ下の全ファイルを取得
  84. path = adir + '/**/*'
  85. files = glob.glob(path,recursive=True)
  86. #個々のファイルの処理を行う
  87. for file in files:
  88. #ファイルの完全パスを取得
  89. apath = os.path.abspath(file)
  90. #取得したパスがファイル名ならファイル名の変換を行う
  91. if os.path.isfile(apath) == True:
  92. #ファイル名部分を取得
  93. file_name = os.path.basename(apath)
  94. #ディレクトリ名部分を取得
  95. dir_name = os.path.dirname(apath)
  96. #ファイル名をUTF-8からSJISに変換する
  97. result = conv.convert(file_name)
  98. #変換不能文字が存在する場合、以下の処理を行う
  99. if result != None:
  100. #変換後のファイル名の完全パスを作成
  101. apath_new = dir_name + "\\" + result
  102. #変換後のファイルが既に存在するならエラーメッセージを追記
  103. err_msg = ""
  104. if os.path.exists(apath_new) == True:
  105. err_msg = "変更後のファイル名が存在します"
  106. #listの場合
  107. if func == 1:
  108. #画面に表示して、次の処理へ
  109. if file_count == 0:
  110. log_print("chcp 65001")
  111. log_print(f'rename\t"{apath}"\t"{result}"\t{err_msg}')
  112. file_count += 1
  113. continue
  114. #execの場合
  115. msg = f"{apath}\t==>\t{result}"
  116. #変更後のファイルが既に存在するならリネームせず、次の処理へ
  117. if os.path.exists(apath_new) == True:
  118. err_files.append(msg)
  119. err_count += 1
  120. continue
  121. #リネーム実行
  122. os.rename(apath,apath_new)
  123. #リネーム完了メッセージ
  124. log_print(msg)
  125. ren_count += 1
  126.  
  127. #list又はbatchの場合
  128. if func == 1:
  129. log_print(f"処理終了 リネーム対象となるファイル件数={file_count}")
  130. log_close()
  131. sys.exit(0)
  132. #exec指定ありの場合
  133. log_print(f"処理終了 リネーム件数={ren_count}")
  134. if err_count > 0:
  135. log_print(f"以下の{err_count}件のファイルがリネームできませんでした")
  136. for fname in err_files:
  137. log_print(fname)
  138. log_close()
  139. sys.exit(0)
  140.  
Runtime error #stdin #stdout 0.02s 9468KB
stdin
Standard input is empty
stdout
指定されたディレクトリ下のファイルについて再帰的に以下の処理行う
./prog.py P1 P2
P1:機能コード
   list  :SJISに変換できないファイルの一覧を出力する
   exec  :SJISに変換できないファイルをSJISに変換可能なファイルにリネームする
P2:ディレクトリ名