退屈なことをPythonにやってもらうための演習の回答[9.7.3]
白地です。
『退屈なことはPythonにやらせよう』演習プロジェクトの9.7.3の、自分なりの解答です。
1箇所よくわからなくてギブアップしてしまったのですが、そのまま公開します。
#! python3
# 9.7.3 連番の飛びを埋める
# ひとつのフォルダの中で、
# spam001.txt、spam002.txt などの、指定した接頭辞を持つ連番ファイルを探し出し、
# 連番が飛んでいる箇所をみつけて
# 番号の飛びを埋めるように後に続くファイルの名前を変更する
import sys, os, re
# 接頭辞・拡張子を定義
designated_prefix = "spam"
designated_extension = "txt"
# フォルダ指定
# 第1引数を見る(エラーは強制終了)
try:
dirpath = sys.argv[1]
except IndexError:
print('Please specify the file you want to convert to argument.')
sys.exit(1)
# ディレクトリかどうか確認し、ディレクトリでなければ強制終了
if os.path.isdir(dirpath)==False :
print('Please specify the Dir.')
sys.exit(1)
# 正規表現でファイル名を確認、リストに入れる。
listed_files = []
filename_regex = re.compile(r'^%s[0-9]{3}\.%s' %(designated_prefix,designated_extension))
for file in os.listdir( dirpath ) :
result = filename_regex.search(file)
if result is not None :
listed_files.append(file)
#TODO ちゃんと並び替わっているのかわからない
sorted(listed_files)
# 仮のファイル名へ置換
for (filename,m) in zip(listed_files,range(1,len(listed_files)+1)):
new_filename = '_'+designated_prefix+str(m).zfill(3)+'.'+designated_extension
listed_files[m-1] = new_filename
os.rename( os.path.join(dirpath,filename), os.path.join(dirpath,new_filename) )
# 本当のファイル名へ置換
for (filename,n) in zip(listed_files,range(len(listed_files))):
os.rename( os.path.join(dirpath,listed_files[n]),os.path.join(dirpath,listed_files[n].replace('_','')) )
方向性
まず接頭辞・拡張子を指定していまいます(本当は何かで指定させた方がいいのかな?)。
指定された接頭辞・拡張子を持ったファイルを、受け取ったフォルダの中で探し出して、リストに突っ込みます。
注意として書いてあったような、数字が飛んでいることで違うファイルをリネームしてしまうことがないように、頭に「_」を付けたファイル名にリネームしてから、その「_」を削除するようにしました。
まったくスマートではないやり方ですが、間違いにはならないのではと思っています。
ギブアップしたところ
sorted関数でリストを並び替える検証が出来ず、その点はギブアップしました。
私の環境(Windows10)だと、そもそもファイルをリストに入れた時点で昇順にソートされてしまっていて、これが果たして正しく動くのかは自信がありません。
参考にしたサイト
正規表現の指定の際に、複数の変数を使う場合のやり方(タプルによる置換)→http://php6.jp/python/2011/01/21/string_format/
for文で複数のリストをまとめて処理するやり方→https://uxmilk.jp/13726
※n=n+1みたいに順番にやるやり方が素直な気がします。何かスマートなやり方がありそうだと調べてみたら発見したので使ってみました。
発展課題について
スルーしてしまいます。なんとなく頭で考えたところだけ。
題意が読み取りづらいのですが、「指定した1つの数値 x だけを飛ばして、そこにファイルを入れられるようにする」とします。
何かの手段でその数値を指定させた上で、上の自分の回答でいうところの最初のfor文の中で x が来たときだけ飛ばし、その代わりfor文の回数を1回増やせばいいのではないかと思います。ファイル数を超えた数値が指定されていないかだけチェックする必要がありそう。
というところでここはひとつ。
この記事が気に入ったらサポートをしてみませんか?