おうち時間の増加によってさらなる売上を伸ばしているらしいニンテンドースイッチ。
ゲーム画面のスクリーンショットをワンタッチで撮影することができるボタンを備えていて、撮影した写真をスマホに送ったり、直接SNSに投稿したりすることができます。
前提
画像のディレクトリ構成
画像は本体またはSDカードに保存されますが、SDカードをPCに差し込んで中を除くと以下のようなディレクトリ構成になっていることがわかります。
年 / 月 / 日 / 年月日時間_xxxxxxxxx.jpg
メリット
- 画像が撮影日ごとになっているのは単純にわかりやすい
- 「ああ、この時こんなソフトで遊んでたなあ」と思い出に更けやすい
デメリット
- 探したい画像がある場合に一覧で探せない(探しづらい)
- いちいち日付ディレクトリまでくだるのがめんどくさい
対象はSwitch二台分
僕はSwitchを二台持っているので、今回はそれぞれの画像ルートディレクトリを下記のような構成で配置しておきます。
やりたいこと
下記のように、ひとつのディレクトリに全画像を集結させ、一覧性を高めたい!
方法
たぶんshellでもできるけど、なんとなくPythonを使ってみたい。
(Pythonならでは、じゃないのでPythonサイコー!とはなりません)
ソースコード
初心者過ぎてコードを正しく解説できる自信はないし、何より「もっとこう書けるよ?」的な感じのご意見もあると思うのでさっさと結論を貼ります。
import os
import glob
import shutil
from pathlib import Path
# ベースディレクトリ
base_dir = "/Users/hogehoge/Desktop/Game/Album"
# なければ出力ディレクトリを作成
output_dir = "/Users/hogehoge/Desktop/output"
Path(output_dir).mkdir(exist_ok=True)
# ファイルコピー関数
def func(input_dir):
# **/*.jpgにより、サブディレクトリまで探索
for i, img_path in enumerate(Path(input_dir).glob("**/*.jpg")):
# 保存ファイルパス <output_dir>/<元のファイル名>.jpg
save_path = Path(output_dir) / img_path.name
# ファイルをコピー(img_path => save_path)
shutil.copyfile(img_path, save_path)
# なんとなく枚数カウント
cnt =+ i
print(cnt + 1) # 最後に枚数出力
if __name__ == '__main__':
# ベース配下のディレクトリの絶対パスを取得(recursive = サブディレクトリまで見るかどうか)
paths = map(os.path.abspath, glob.glob(base_dir + '/*', recursive=False))
# ディレクトリだけにフィルタリングして、listで返す
paths = list(filter(os.path.isdir, paths))
# 1つずつ処理する
for i, p in enumerate(paths):
print('[%s / %s] Start %s' % (i + 1, len(paths), p))
func(p)
ちょこっとだけ解説(備忘録)
Path("hoge/fugafuga")
Path(output_dir).mkdir(exist_ok=True)
これにより与えられた文字列をディレクトリパスとして扱うことができるらしいです。
__name__
if __name__ == '__main__':
プログラミングでよくある冒頭のおまじない的な感じです。(importされた時の挙動制御みたいな意味合いがあるらしいです)
ディレクトリのリストに対する操作諸々
paths = map(os.path.abspath, glob.glob(base_dir + '/*', recursive=False))
paths = list(filter(os.path.isdir, paths))
最初のmap
関数で、base_dir/*
にあるファイルやディレクトリの絶対パス(abspath)を取得して、次のfilter
関数で、paths
の中からディレクトリだけ(isdir)を取得します。(返却はlist型)
今回はbase_dir
配下に、SwitchとSwitch_liteという二つのフォルダがあるので、最終的なpaths
は以下のようになりました(整形済み)。
[
'/Users/hogehoge/Desktop/Game/Album/Switch_lite',
'/Users/hogehoge/Desktop/Game/Album/Switch'
]
enumerate(paths)
forループの中で使うとインデックス番号を取得できるらしいです。(以下の場合、iがインデックス番号)
for i, p in enumerate(paths):
glob
glob.glob(base_dir + '/*', recursive=False)
Path(input_dir).glob("**/*.jpg")
同じglob
関数ですが、前者はbase_dir/*
配下のファイルやディレクトリ、後者はinput_dir
配下の*.jpg
ファイルを再帰的に取得します。
ちなみに、前者は後者のような書き方でも大丈夫そうです。ただ、どっちがいいかはわからないです。
Path(base_dir).glob("*")
shutil.copyfile
shutil.copyfile(img_path, save_path)
img_path
をsave_path
にコピーするらしいです。shutil
は読み方、エスエイチユーティルでいいのかな。
というわけで趣味の延長ですが、Nintendo Switchで撮影した画面キャプチャをもともとのディレクトリ構造からひとつのディレクトリに集結させるPythonを書いてみた話でした。