目次
はじめに
作成した経緯
実行環境
フォルダダイアログを使ったフォルダパスの指定方法_追加
月と日の取得方法
フォルダ内のすべてのファイル名の取得方法
フォルダ内のファイルの最終更新月日の取得方法
最終更新月日のフォルダの作成方法
最終更新月日ごとでフォルダに振り分ける方法
ソースコード
結果
注意点
まとめ
はじめに
今回は、投稿月と投稿日を tkcalendar
のウィジェットである DateEntry
(クリックでDateEntryのドキュメントへ)を用いて指定しその日付をもとに特定のフォルダ内の最終更新月日のファイルを振り分けるプログラムを作成したのでそれについて紹介したいと思います。
よろしければこちらもどうぞ!!
作成した経緯
Qiita
に記事を投稿しているときにこんなことをやりたいと思いました。
- これまで作成したものが入っているフォルダ内のファイルを投稿日付ごとに振り分けたい
- GitHubをやっており後でデータを格納する際に分かりやすくさせたかった
- これまでの作成したものが入っているフォルダ内のファイルを一括して振り分けたい
- 投稿した都度日付の名前のフォルダを作り更新日付ごとにファイルを振り分けるのは大変だった
- 時間があるときにまとめて処理を実行させたかった
このような経緯から作成しました。
実行環境
実行環境は次の通りです。
実行環境
-
環境
Windows10
Python 3.10.5
-
ライブラリ
tkcalendar 1.5.0
os
・ datetime
・ tkinter
は、標準ライブラリなので特に気にしなくても大丈夫です!!
処理内容とモジュール・ライブラリの対応を分かりやすく表にすると次の通りです。
説明
処理内容 | モジュール・ライブラリ |
---|---|
ファイル操作 | os |
ファイルの更新月日の取得 | datetime |
GUI作成 | tkinter |
カレンダー形式のGUI作成 | tkcalendar |
フォルダダイアログを使ったフォルダパスの指定方法_追加
前回のプログラムだと前もってフォルダを指定した状態で日付を指定していました。
この方法だと自由度が低いと感じたため前回のプログラムに新しく追加しました。
こちらのソース
では、 tkinter
の filedialog.askdirectory
を使うことでフォルダダイアログを tkinter
を用いて表示できるそうです。
この方法を用いてフォルダダイアログを表示させました。
月と日の取得方法
tkcalendarの公式ドキュメントを見ると、 get_date
で datetime
形式のデータを取得できるらしいのでこれを使いました。
こちらのソース
では、 <<DateEntrySelected>>
というキーイベントで tkcalendar
でのカレンダーの日付を取得できるらしいのでこれを使いました。
公式ドキュメントにあった get_date
から月( month
)の部分と日( day
)の部分を get_date().month
と get_date().day
で拾えるっぽいのでこの方法で tkcalendar
から月と日を取得しました。
フォルダ内のすべてのファイル名の取得方法
こちらのソース
によると、
os.listdir
でフォルダ内のファイル一覧を取得できる
らしいので、この方法でフォルダ内のすべてのファイル名を取得しました。
フォルダ内のファイルの最終更新月日の取得方法
こちらのソース
によると、
最終更新日時は
mtime
で取得できる
らしいので、この方法でファイルの最終更新日時を取得しました。
また、公式ドキュメントによると、 datetime.datetime
クラスの属性には month
属性と day
属性がありこれらの属性にアクセスすることで月と日を取得できるらしいのでこの方法でファイルの最終更新日時からファイルの最終更新月日を取得しました。
最終更新月日のフォルダの作成方法
こちらのソース
によると、
os.makedirs
でフォルダを作成できる
引数であるexist_ok
をTrue
に指定すると既に存在しているフォルダを指定してもエラーにならない
らしいので、この方法でフォルダを作成しました。
また、この処理を次の条件のとき
- フォルダ内のファイルの最終更新月日の取得方法で取得された月が月と日の取得方法で取得された月から1を引いた数でありフォルダ内のファイルの最終更新月日の取得方法で取得された日が月と日の取得方法で取得された日よりも大きい場合
- フォルダ内のファイルの最終更新月日の取得方法で取得された月が月と日の取得方法で取得された月でありフォルダ内のファイルの最終更新月日の取得方法で取得された日が月と日の取得方法で取得された日以下の場合
に実行しました。
また、フォルダ名は月と日の取得方法を string
型(文字型)に型変換して作成しました。
具体例
例えば、
tkcalendar
で「8」月「2」日と入力された場合
→ ファイルの最終更新月日が「7」月「2」日以降か「8」月「2」日まで
としました。
こうすることで、前月分のデータも参照することができるようにしました。
月日を指定する時には順次指定してください。
指定した月日のフォルダ内に指定した月日以前のデータも含んでファイルに入ってしまいます
最終更新月日ごとでフォルダに振り分ける方法
こちらのソース
によると、
os.rename
でファイルを移動させることができる
らしいので、この方法でファイルを移動させました。
また、対象のフォルダ(最終更新月日でフォルダ分けさせたいファイルが格納されているフォルダ)内にファイルがある場合に実行するようにしました。
こちらのソース
の情報からファイルの存在確認を行う処理を実装しました。
ソースコード
下にソースコードを示します。おそらく実行環境で示した環境では動くはず。
ソースコード
import os #ファイル操作のためにインポート
import datetime #ファイルの更新月日を取得するためにインポート
from tkinter import * #tkinterライブラリのすべてのモジュールをインポート
from tkinter import filedialog
from tkcalendar import DateEntry #tkcalendarの入力を取得するためにインポート
dir = filedialog.askdirectory(initialdir='C:\\') #-*追加部分*-フォルダの指定(tkinter.filedialogを使ったフォルダダイアログで指定(初期フォルダをC:\としている))
root=Tk() #tkinterのセットアップ
root.title("カレンダー") #「カレンダー」という名前のウインドウを作成
date_form = DateEntry(locale='ja_JP') #tkcalendarをデータ取得用のカレンダー形式の要素(ウィジェット)を作成(locale='ja_JP'と指定することで日本語形式で設定)
def func(event): #tkinterの処理関数を定義
date_get = date_form.get_date() #tkcalendarから日付を取得
month = date_get.month #date_get中の月(month)の部分を取得
day = date_get.day #date_get中の日(day)の部分を取得
files=os.listdir(dir) #「python」フォルダの中のすべてのファイル一覧を取得
for file in files: #すべてのファイルについて処理を実行
date = datetime.datetime.fromtimestamp(os.path.getmtime(dir+"/"+file)) #最終更新日時をタイムスタンプ形式で取得
if ((date.month == month-1 and date.day > day) or (date.month == month and date.day <= day)):
'''
date中の月(date.month)がdate_get中の月(month)-1でありdate中の日(date.day)がdate_get中の日(day)より大きいか、date中の月(date.month)がdate_get中の月(month)であり
date中の日(date.day)がdate_get中の日(day)以下である場合
ex)
「8」月「2」日と入力された場合 → 「7」月「3」日以降から「8」月「2」日まで
※この処理だと順番に日付を指定しないとすべてのデータが指定した日付のフォルダに格納されてしまうという問題が発生する
'''
os.makedirs(dir+"/"+str(month)+"_"+str(day),exist_ok=True) #フォルダが存在しない場合には、指定した日付のフォルダを「python」フォルダの下に配置
if(os.path.isfile(dir+"/"+file)): #上のフォルダがある場合に処理を実行
os.rename(dir+"/"+file,dir+"/"+str(month)+"_"+str(day)+"/"+file) #条件に一致したファイル(指定した日付までのファイル)を作成したフォルダ
#(指定した日付のフォルダ)の配下に移動させる
date_form.bind("<<DateEntrySelected>>",func) #tkcalendarでのカレンダーで任意の日付が押されたときに処理関数(func)を実行
date_form.pack() #カレンダー形式で作成したウィジェット(date_form)を画面上に配置
root.mainloop() #GUIの表示(この処理がないと一瞬表示されて消えるので表示されていないように見える)
結果
下に結果を示します。
この入力画面を使って投稿月日を指定します。
処理前のフォルダ内がこちらです。
例えば、「7」月「28」日と入力した場合にはこうなります。
ちゃんと「7」月「28」日という名前のフォルダが作成されています。
フォルダの中身がこちらです!!
ちゃんと「7」月「28」日までのファイルが格納されています。
注意点
最終更新月日のフォルダの作成方法でも示したように投稿月日を日付順に指定しないとそれ以前に投稿したデータも含んでフォルダに格納されてしまいます。
具体的にはこんな感じになります。
まとめ
今回は、投稿月日を指定することでフォルダ内のファイルを最終更新月日から投稿月日ごとに振り分けることを行いました。
この記事が実際に役に立つかどうかは分かりませんが、誰かの役に立ってくれると嬉しいです。
記事を執筆する余力があれば、次回も記事を投稿する予定です。
次回の予定としては、今回振り分けたフォルダごとに拡張子から「結果・素材」フォルダと「ソースコード」フォルダにデータを振り分けるプログラムを作成できたのでそれに関する記事を投稿予定です。