スナックelve 本店

バツイチ40代女の日記です

君はコードなんて読まないと思いながら~

f:id:elve:20220102214049p:plain

今までの流れ

googleフォトが50%超えて警告&MicrosoftOfficeサブスク加入でOneDrive1T化
googleフォト→OneDriveを企てる
googleフォト→エクスポート
Typescriptで処理する→激重
Pythonで処理する→軽い~

あれれ~?

むむ? OneDriiveの「写真」の並びがおかしい・・・
昨日に2020年のデータとかでる・・・。作成日時上書かないとダメかな?
結果:同期待中。←いい感じになりました!!

コード

googleフォト→エクスポートの時に同時に吐かれるjsonファイルも見て一番古い日付でファイルのタイムスタンプ上書きするコードです。
C:\Users\user\Desktop\Takeout\ の下に2013-2021のフォルダを作り、更にそのフォルダの中に01-12のフォルダを作ります。
C:\Users\user\Desktop\Takeout\Google フォト\ の下のファイルのタイムスタンプ、exifタグ、jsonファイルから一番古い日付を取得してタイムスタンプを上書き、年、月に応じたフォルダへ移動します。
jsonファイル削除するので注意

from PIL import Image
import datetime
import os
import json
import re
import win32_setctime
# ディレクトリ作成


def makeDir():
    b = "C:\\Users\\user\\Desktop\\Takeout\\"
    for y in range(2013, 2022):
        try:
            os.mkdir(b + format(y, '0>4'))
            for m in range(1, 13):
                os.mkdir(b + format(y, '0>4') + "\\" + format(m, '0>2'))
        except:
            continue

# exifタグから日付取得


def getImgFileMinDate(im):
    exif = im.getexif()
    index = [306, 36867, 50971, 36867, 36868]
    d = []
    for i in index:
        if i in exif:
            d.append(datetime.datetime.strptime(exif[i],r'%Y:%m:%d %H:%M:%S'))
    im.close()
    del im

    minD = datetime.datetime.today()
    for dd in d:
        if minD > dd:
            minD = dd
    return minD

# ファイルのタイムスタンプ


def getFileMinDate(flfilename):
    f = os.stat(flfilename)
    d = []
    d.append(datetime.datetime.fromtimestamp(f.st_ctime))
    d.append(datetime.datetime.fromtimestamp(f.st_atime))
    d.append(datetime.datetime.fromtimestamp(f.st_mtime))
    if "st_birthtime" in f:
        d.append(datetime.datetime.fromtimestamp(f.st_birthtime))
    minD = datetime.datetime.today()
    for dd in d:
        if minD > dd:
            minD = dd
    del f
    return minD

# jsonファイルから


def getJsonMindate(filename):
    # hogehoge.xxx hogehoge.xxx.json のセット
    if not os.path.isfile(filename):
        tmp = filename.split(".")
        filename2 = ""
        # hogehoge.xxx hogehoge.json のセット
        for t in range(0, len(tmp)-2):
            filename2 = filename2+tmp[t]+"."
        filename2 = filename2+"json"
        # hogehogefuga.xxx hogehogefug.xxx.json のセット
        if not os.path.isfile(filename2):
            filename2 = ""
            for t in range(0, len(tmp)-2):
                filename2 = filename2+tmp[t]+"."
            filename2 = filename2[0:len(filename2)-2]+"."+tmp[len(tmp)-1]
        # hogehogefuga(1).xxx hogehogefug.xxx(1).json のセット
        if not os.path.isfile(filename2):
            filename = re.sub(r'(.*)(\(.*\))(\..*)(\..*)',
                              r'\1\3\2.json', filename)
        else:
            filename = filename2

    try:
        f = open(filename, 'r', encoding='utf-8')
    except OSError as err:
        print("OS error: {0}".format(err))
        return datetime.datetime.today()
    except:
        print("err: "+filename)
        return datetime.datetime.today()

    j = json.load(f)
    d = []
    k = j.keys()
    for kk in k:
        if re.match('.*Time.*', kk):
            if "formatted" in j[kk]:
                d.append(datetime.datetime.strptime(j[kk]["formatted"],r'%Y/%m/%d %H:%M:%S UTC'))
    minD = datetime.datetime.today()
    for dd in d:
        if minD > dd:
            minD = dd
    del j
    del f
    os.remove(filename)
    return minD
# フォルダ削除


def deleteDir():
    baseP = "C:\\Users\\user\\Desktop\\Takeout\\"

    yDirList = os.listdir(baseP)
    for y in yDirList:
        for m in range(1, 13):
            try:
                fileList = os.listdir(baseP + y + "\\" + format(m, "0>2"))
                if not fileList:
                    os.rmdir(baseP+y+"\\" + format(m, "0>2"))
            except:
                continue
    for y in yDirList:
        try:
            fileList = os.listdir(baseP + y + "\\")
            if not fileList:
                os.rmdir(baseP+y+"\\")
        except:
            continue

# main
baseP = "C:\\Users\\user\\Desktop\\Takeout\\Google フォト\\"
makeDir()

yDirList = os.listdir(baseP)
for y in yDirList:

    files = os.listdir(baseP + y)

    files_file = [f for f in files if os.path.isfile(
        os.path.join(baseP, y, f))]
    del files
    for f in files_file:
        p = baseP+y+"\\"+f
        try:
            files = os.open(p, os.O_RDONLY)
        except:
            continue

        if (f.endswith('.json')):
            os.close(files)
            del files
            continue
        else:
            os.close(files)
            del files
            try:
                im = Image.open(p, encoding='utf-8')
                miD = getImgFileMinDate(im)
            except:
                miD = getFileMinDate(p)

            nFName = p+".json"

            miD2 = getJsonMindate(nFName)
            if miD > miD2:
                miD = miD2
            yD = miD.strftime('%Y')
            mD = miD.strftime('%m')
            nf = "C:\\Users\\user\\Desktop\\Takeout\\" + yD + "\\" + mD + "\\" + f
            try:
                win32_setctime.setctime(p, miD.timestamp())
                os.utime(p, (miD.timestamp(), miD.timestamp()))
                os.rename(p, nf)
            except OSError as err:
                print(p)
                print("OS error: {0}".format(err))
            except:
                print(os.error)
deleteDir()
del f
del yDirList

ご利用は自己責任で。

参考

PythonでJSON 読み込み - Qiita
【Python】ファイルの拡張子を取得する | 鎖プログラム
ファイルの拡張子を取得する - Python Tips
Pythonでファイル名から拡張子を取得する - Python入門
Python パスから拡張子なしのファイル名を取得する | Delft スタック
os --- 雑多なオペレーティングシステムインターフェース — Python 3.10.0b2 ドキュメント
Pythonのos.open()メソッド
【Python】startswith・endswith 指定した文字列で始まるか?終わるか? | 鎖プログラム
Pythonでリストのサイズ(要素数)を取得 | note.nkmk.me
Pythonでワイルドカードを活用してファイルリストを取得する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Pythonで文字列のリスト(配列)の条件を満たす要素を抽出、置換 | note.nkmk.me
Pythonのglobモジュールを利用して指定パス内のjsonファイル一覧を取得する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
PythonにおいてのJSONファイルの取扱いあれこれ - Qiita
Python | 辞書に含まれるすべてのキーと値を取得する
Pythonでstrftimeを使う方法【初心者向け】 | TechAcademyマガジン
Pythonでファイルの存在を確認する方法【初心者向け】現役エンジニアが解説 | TechAcademyマガジン
Python | 辞書でキーを指定して値を取得する
Pythonの正規表現モジュールreの使い方(match、search、subなど) | note.nkmk.me
pythonでファイルの存在を確認する - Qiita
Python文字列操作マスター - Qiita
re --- 正規表現操作 — Python 3.10.0b2 ドキュメント
re --- 正規表現操作 — Python 3.10.0b2 ドキュメント
Python 3.x - pythonでjsonを読み込みたい|teratail
JSON - pythonのjson.loadsで文字化けを防ぐ方法に関して|teratail
python json load set encoding to utf-8 - Stack Overflow
【Python】ファイルのタイムスタンプを変更するコード例【作成日時・更新日時・アクセス日時を変更する】 | シラベルノート
Pythonでファイル・ディレクトリを削除するos.remove, shutil.rmtreeなど | note.nkmk.me
PythonでISO 8601形式の文字列と日時datetimeを相互変換 | note.nkmk.me
datetime --- 基本的な日付型および時間型 — Python 3.10.0b2 ドキュメント
Python | 日付や時刻を表す文字列からインスタンスを生成する
[解決!Python]日付や時刻をYYMMDDhhmmssなどの形式に書式化するには:解決!Python - @IT