スナックelve 本店

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

かるがるぅ~

f:id:elve:20220101130422p:plain

googleフォトをOneDriveに年ごと月ごとフォルダに分けたい・・・ただそれだけなのにクソ重くてどうしようかと思っていたのですが、Pythonでサクッと終わりました(;´Д`)
snack.elve.club

適材適所ですな!!!(ノД`)ナェルシク
たぶんTypeScriptはこういうローカルいじるんじゃなくてサーバーでweb系コンテンツいじる時に力を発揮するんだと思います(;´Д`)

まず、OneDriveと同期してるフォルダいじると毎回同期で時間がかかるので別のフォルダに一旦移してからOneDriveに移すことにしました。
年フォルダの中に01~12の月フォルダを入れます。

import os
b = "C:\\Users\\user\\Desktop\\Takeout\\"
for y in range(2000, 2022):
    os.mkdir(b + format(y, '0>4'))
    for m in range(1, 13):
        os.mkdir(b + format(y, '0>4') + "\\" + format(m, '0>2'))

for分の書き方すらググらんとわからんレベルですよ(;´Д`)

from PIL import Image
import datetime
import os
# 0x0132	306	Image	Exif.Image.DateTime
# 0x9003	36867	Image	Exif.Image.DateTimeOriginal
# 0xc71b	50971	Image	Exif.Image.PreviewDateTime
# 0x9003	36867	Photo	Exif.Photo.DateTimeOriginal
# 0x9004	36868	Photo	Exif.Photo.DateTimeDigitized
#

#画像ファイルの移動
def moveImgFile(im):
    exif = im.getexif()
    index = [306, 36867, 50971, 36867, 36868]
    d = []
    for i in index:
        if i in exif:
            tmp = exif[i].split()
            d.append(datetime.date.fromisoformat(tmp[0].replace(":", "-")))
    #ここでim開放しないとパーミションエラーが出る(ハマった)
    im.close()
    del im

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

    mD = minD.strftime('%m')
    try:
        os.rename(baseP + y + "\\" + f,
                  "C:\\Users\\user\\Desktop\\Takeout\\" + yD + "\\" + mD + "\\" + f)
    except OSError as err:
        print("OS error: {0}".format(err))
    except:
        print(os.error)
    return

#画像以外の移動
def moveFile(flfilename):
    f = os.stat(flfilename)
    d = []
    d.append(datetime.datetime.fromtimestamp(f.st_ctime).date())
    d.append(datetime.datetime.fromtimestamp(f.st_atime).date())
    d.append(datetime.datetime.fromtimestamp(f.st_mtime).date())
    if "st_birthtime" in f:
        d.append(datetime.datetime.fromtimestamp(f.st_birthtime).date())
    minD = datetime.date.today()
    for dd in d:
        if minD > dd:
            minD = dd

    mD = minD.strftime('%m')
    filename = os.path.basename(flfilename)
    try:
        os.rename(flfilename,
                  "C:\\Users\\user\\Desktop\\Takeout\\" + yD + "\\" + mD + "\\" + filename)
    except OSError as err:
        print("OS error: {0}".format(err))
    except:
        print(os.error)
    del f
    return

#メイン処理
baseP = "C:\\Users\\user\\Desktop\\Takeout\\Google フォト\\"

yDirList = os.listdir(baseP)
for y in yDirList:
    yD = y.replace("Photos from ", "")
    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:
        try:
            im = Image.open(baseP + y + "\\" + f)
            moveImgFile(im)
        except:
            moveFile(baseP + y + "\\" + f)
del yDirList

おまけ:空フォルダ削除

import os

baseP = "C:\\Users\\user\\Desktop\\Takeout\\"

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

参考

[Python入門]ファイル操作と例外処理:Python入門(1/2 ページ) - @IT
組み込み関数 — Python 3.10.0b2 ドキュメント
os --- 雑多なオペレーティングシステムインターフェース — Python 3.10.0b2 ドキュメント
stat --- stat() の結果を解釈する — Python 3.10.0b2 ドキュメント
string --- 一般的な文字列操作 — Python 3.10.0b2 ドキュメント
8. エラーと例外 — Python 3.10.0b2 ドキュメント
ExifTags Module — Pillow (PIL) examples
[Python] フォルダやファイルのコピー、移動、削除(shutilモジュール) | Hbk project
【python3】forとifを一行で書きたい|yucco|note
Pythonで現在時刻・日付・日時を取得 | note.nkmk.me
Pythonの基本的なエラー一覧とその原因の確認方法 | note.nkmk.me
Python, formatで書式変換(0埋め、指数表記、16進数など) | note.nkmk.me
Pythonの三項演算子(条件演算子)でif文を一行で書く | note.nkmk.me
Pythonでリスト(配列)に要素を追加するappend, extend, insert | note.nkmk.me
Pythonでファイル名・ディレクトリ名の一覧をリストで取得 | note.nkmk.me
Pythonでパス文字列からファイル名・フォルダ名・拡張子を取得、結合 | note.nkmk.me
Pythonでディレクトリ(フォルダ)を作成するmkdir, makedirs | note.nkmk.me
Pythonでファイル・ディレクトリを削除するos.remove, shutil.rmtreeなど | note.nkmk.me
Python, pathlibでファイル一覧を取得(glob, iterdir) | note.nkmk.me
Pythonの画像処理ライブラリPillow(PIL)の使い方 | note.nkmk.me
Pythonでファイル・ディレクトリを移動するshutil.move | note.nkmk.me
Pythonで文字列を分割(区切り文字、改行、正規表現、文字数) | note.nkmk.me
Python日付型 - Qiita
Python配列のループ処理 - Qiita
【Python】PillowライブラリのExifTags名前一覧を取得 - Qiita
[Python]ファイル/ディレクトリ操作 - Qiita
WindowsでのPython外部モジュール導入のはまりどころ - Qiita
Python - stat — stat()の結果を解釈する - Source code:Lib/stat.py stat の結果を解釈するためのモジュール定義定数と機能 os.stat() 、 os.fstat() と os - 日本語
Pythonでos.remove()を使って条件を指定してファイルを削除しようとするとPermissionErrorになる - プログラミング素人のはてなブログ
【Python】Pillow(PIL)のインストールをわかりやすく解説 | ジコログ
file io - Error with os.open in Python - Stack Overflow
pythonのwin環境での実行時、ファイル削除しようとするとパーミッションエラー。(またpythonで変に詰まったので備忘録) - プログラミングを趣味にしたい
Pythonのlistdir関数の使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Python - 「プロセスはファイルにアクセスできません。」の解決法について|teratail
Python - [WinError 32] プロセスはファイルにアクセスできません。別のプロセスが使用中です。:|teratail
python for文を初心者向けに解説!for文基礎はこれで…|Udemy メディア
python : PermissionError:[WinError 32]別のプロセスで使用されているため、プロセスはファイルにアクセスできません。
Pythonでディレクトリ(フォルダ)が空か確認する - ほぼ中立ブログ
Python | ファイル名またはディレクトリ名を変更する
関数の定義: ゼロからのPython入門講座 - python.jp
【Python入門】メモリの解放や効率的に使う方法をマスターしよう! | 侍エンジニアブログ
python — Pythonでファイルが開いていない(他のプロセスで使用されていない)