📝

tkcalendarからの指定日付を使ったデータの振り分け(追記)

2023/08/17に公開
1

この記事はQiitaの記事の転載です!!

元記事はこちら

https://qiita.com/blueman/items/609e5a4be741ffa4983f


目次

はじめに
作成した経緯
実行環境
フォルダダイアログを使ったフォルダパスの指定方法_追加
月と日の取得方法
フォルダ内のすべてのファイル名の取得方法
フォルダ内のファイルの最終更新月日の取得方法
最終更新月日のフォルダの作成方法
最終更新月日ごとでフォルダに振り分ける方法
ソースコード
結果
注意点
まとめ

はじめに

今回は、投稿月投稿日tkcalendar のウィジェットであるDateEntryを用いて指定しその日付をもとに特定のフォルダ内の最終更新月日のファイルを振り分けるプログラムを作成したのでそれについて紹介したいと思います。


マイページについて

https://qiita.com/blueman


X(Twitter)について

https://twitter.com/0ca00118726208m


Qiitaについて

作成した経緯

Qiitaに記事を投稿しているときにこんなことをやりたいと思いました。

  • これまで作成したものが入っているフォルダ内のファイルを投稿日付ごとに振り分けたい
    • GitHubをやっており後でデータを格納する際に分かりやすくさせたかった
  • これまでの作成したものが入っているフォルダ内のファイルを一括して振り分けたい
    • 投稿した都度日付の名前のフォルダを作り更新日付ごとにファイルを振り分けるのは大変だった
    • 時間があるときにまとめて処理を実行させたかった

このような経緯から作成しました。

実行環境

実行環境は次の通りです。

実行環境
  • 環境

    • Windows10
    • Python 3.10.5
  • ライブラリ

    • tkcalendar 1.5.0

処理内容モジュール・ライブラリの対応を分かりやすく表にすると次の通りです。

説明
処理内容 モジュール・ライブラリ
ファイル操作 os
ファイルの更新月日の取得 datetime
GUI作成 tkinter
カレンダー形式のGUI作成 tkcalendar

フォルダダイアログを使ったフォルダパスの指定方法_追加

前回のプログラムだと前もってフォルダを指定した状態で日付を指定していました。
この方法だと自由度が低いと感じたため前回のプログラムに新しく追加しました。

こちらのソース

https://pg-chain.com/python-filedialog-dir

では、tkinterfiledialog.askdirectory を使うことでフォルダダイアログをtkinterを用いて表示できるそうです。
この方法を用いてフォルダダイアログを表示させました。

月と日の取得方法

tkcalendarの公式ドキュメントを見ると、get_datedatetime 形式のデータを取得できるらしいのでこれを使いました。

こちらのソース

https://www.beyoufree.com/2022/04/29/python-tkinterでカレンダーの値を取得する/

では、
<<DateEntrySelected>> というキーイベントで tkcalendar でのカレンダーの日付を取得できるらしいのでこれを使いました。

公式ドキュメントにあった get_date から月(month)の部分と日(day)の部分を get_date().monthget_date().day で拾えるっぽいのでこの方法で tkcalendar から月と日を取得しました。

フォルダ内のすべてのファイル名の取得方法

こちらのソース

https://www.sejuku.net/blog/63568

によると、

os.listdir でフォルダ内のファイル一覧を取得できる

らしいので、この方法でフォルダ内のすべてのファイル名を取得しました。

フォルダ内のファイルの最終更新月日の取得方法

こちらのソース

https://note.nkmk.me/python-os-stat-file-timestamp/

によると、

最終更新日時はmtimeで取得できる

らしいので、この方法でファイルの最終更新日時を取得しました。
また、公式ドキュメントによると、 datetime.datetime クラスの属性には month 属性と day 属性がありこれらの属性にアクセスすることで月と日を取得できるらしいのでこの方法でファイルの最終更新日時からファイルの最終更新月日を取得しました。

最終更新月日のフォルダの作成方法

こちらのソース

https://note.nkmk.me/python-os-mkdir-makedirs/#osmakedirs

によると、

os.makedirsでフォルダを作成できる
引数であるexist_okTrueに指定すると既に存在しているフォルダを指定してもエラーにならない

らしいので、この方法でフォルダを作成しました。

また、この処理を次の条件のとき

に実行しました。

また、フォルダ名月と日の取得方法string型(文字型)に型変換して作成しました。

具体例

最終更新月日ごとでフォルダに振り分ける方法

こちらのソース

https://python-academia.com/file-transfer/

によると、

os.renameでファイルを移動させることができる

らしいので、この方法でファイルを移動させました。
また、対象のフォルダ(最終更新月日でフォルダ分けさせたいファイルが格納されているフォルダ)内にファイルがある場合に実行するようにしました。

こちらのソース

https://note.nkmk.me/python-os-exists-isfile-isdir/

の情報からファイルの存在確認を行う処理を実装しました。

ソースコード

下にソースコードを示します。おそらく実行環境で示した環境では動くはず。

ソースコード
data_separate(time).py
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の表示(この処理がないと一瞬表示されて消えるので表示されていないように見える)


結果

下に結果を示します。

フォルダダイアログ

フォルダダイアログ.JPG


入力画面

入力画面.png
入力画面


この入力画面を使って投稿月日を指定します。

処理前のフォルダ内がこちらです。

処理前のフォルダ内

処理前のフォルダ内.JPG
処理前のフォルダ


例えば、「7」月「28」日と入力した場合にはこうなります。

処理例

処理例.JPG
処理例


ちゃんと「7」月「28」日という名前のフォルダが作成されています。

フォルダの中身がこちらです!!

フォルダ内

フォルダ内.JPG
フォルダ内


ちゃんと 「7」月「28」日までの ファイルが格納されています。

注意点

最終更新月日のフォルダの作成方法でも示したように投稿月日を日付順に指定しないとそれ以前に投稿したデータも含んでフォルダに格納されてしまいます。
具体的にはこんな感じになります。

実行結果

実行結果_1.JPG
対象フォルダ内
実行結果_2.JPG
「8_2」フォルダ内


まとめ

今回は、投稿月日を指定することでフォルダ内のファイルを最終更新月日から投稿月日ごとに振り分けることを行いました。
この記事が実際に役に立つかどうかは分かりませんが、誰かの役に立ってくれると嬉しいです。
記事を執筆する余力があれば、次回も記事を投稿する予定です。
次回の予定としては、今回振り分けたフォルダごとに拡張子から「結果・素材」フォルダと「ソースコード」フォルダにデータを振り分けるプログラムを作成できたのでそれに関する記事を投稿予定です。

Discussion