なんでそんな無駄なアプリを?GoogleDriveには右クリックすれば「このフォルダを同期またはバックアップ」という機能があるよ!
と思われたかもしれない。
私もそれを利用しようとフォルダをバックアップしたのだが、1つ問題があった。
保存容量が少なくなってきている。
しかもバックアップするのはあるファイルだけでいいのに大きなフォルダごとなのでファイル容量が大きくなってしまう。
そこで必要なファイルだけをアップするシステムをGPT様に書いてもらった。ただ、書いてもらって実行するのは簡単なのだが、せっかくだからそのコードをしっかり読み取れるようになりたい。
大昔、HTMLを勉強した時、今のようにブログというものもなく、自分で作るのが主流であった。その頃便利「ホームページビルダー」というHTMLを生成してくれるソフトがIBMから発売されてた。
私はそれで吐き出してもらったHTMLを見てもちんぷんかんぷんだったが、このコードをいじると何が変わるのか?ということを繰り返して覚えた。
しかし、プログラミング言語の場合はいじくるのが難しいので、わからないことはAIに聞けばわかりやすく説明してくれる先生になってくれる。小さな子供が「ねえ、これなに?なんで?」と母親に何度も聞くのと同じことができる。
さて今回のプログラムの超簡単な設計
言語:python
必要なもの:
- GoogleDriveのPC版のアプリ(PC内に生成されるフォルダにつっこむと自動でDriveに保存される)
- タスク スケジューラー(winでは標準装備)
- driveのバックアップするフォルダを指定(存在しない場合は作成)
- バックアップフォルダを指定(フォルダをバックアップする場合)
- バックアップファイルを指定
- driveのフォルダに上書き
タスクスケジューラーで〇日ごとの◯時にこのファイルを実行させる。あまり電源を入れない人は起動時ごとでもいいかもしれない。私はずっと電源が入っており、スリープ中でも叩き起こすようにしてある。
ソースコード
今回、vscode、minicondaの設定ファイルをバックアップするシステムだが、書き換えれば色々活用できるかと。
import os
import shutil
import subprocess
# Google Drive のバックアップフォルダ(フォルダのパスを修正)
GOOGLE_DRIVE_PATH = r"マイドライブのパス"
os.makedirs(GOOGLE_DRIVE_PATH, exist_ok=True) # フォルダを作成(存在しない場合)
# VSCodeのバックアップ対象フォルダ(Windows)
VSCODE_CONFIG = os.path.join(os.path.expanduser("~"), "AppData", "Roaming", "Code", "User")
VSCODE_BACKUP_PATH = os.path.join(GOOGLE_DRIVE_PATH, "vscode_config")
VSCODE_EXTENSIONS_FILE = os.path.join(GOOGLE_DRIVE_PATH, "vscode_extensions.txt")
# Minicondaのバックアップ対象ファイル
CONDARC_FILE = os.path.join(os.path.expanduser("~"), ".condarc") # Miniconda 設定
MINICONDA_ENV_FILE = os.path.join(GOOGLE_DRIVE_PATH, "conda_env.yml") # 環境のエクスポート
BASE_ENV_FILE = os.path.join(GOOGLE_DRIVE_PATH, "conda_base_packages.txt") # Base環境リスト
# 1️⃣ VSCode 設定ファイルのバックアップ(上書き保存)
if os.path.exists(VSCODE_BACKUP_PATH):
shutil.rmtree(VSCODE_BACKUP_PATH) # 既存フォルダを削除
shutil.copytree(VSCODE_CONFIG, VSCODE_BACKUP_PATH) # 最新データをコピー
# 2️⃣ VSCode 拡張機能リストの保存(上書き)
subprocess.run(f"code.cmd --list-extensions > \"{VSCODE_EXTENSIONS_FILE}\"", shell=True)
# 3️⃣ Miniconda 設定ファイル(.condarc)のバックアップ
if os.path.exists(CONDARC_FILE):
shutil.copy(CONDARC_FILE, GOOGLE_DRIVE_PATH)
# 4️⃣ Miniconda 環境のバックアップ(上書き)
subprocess.run(f"conda env export > \"{MINICONDA_ENV_FILE}\"", shell=True)
# 5️⃣ Miniconda base環境のパッケージリスト保存(上書き)
subprocess.run(f"conda list --explicit > \"{BASE_ENV_FILE}\"", shell=True)
print("✅ バックアップ完了!Google DriveのBackupsフォルダに上書き保存しました。")
Code language: PHP (php)
コード解析
ここからは自分の勉強用。なんでこれが必要なのか詳しく知りたい初学者向け。
こちらは随時更新されていく
GOOGLE_DRIVE_PATH = r””
これはバックアップファイル・フォルダを格納するドライブのパス指定
r””の意味
答え:\
を特別な意味を持たない「そのままの文字」として扱う
この r""
は、「生(raw)文字列」 を意味する。r""
を付けると、\
を特別な意味を持たない「そのままの文字」として扱う ことができる。
Pythonでは、Windowsのパスに使われる \
(バックスラッシュ)は特別な意味を持ちます。
\
の特別な意味とは?
たとえば、Pythonの文字列で \n
と書くと「改行」として処理されます。
pythonコピーする編集するtext = "Hello\nWorld"
print(text)
出力結果:
Hello
World
\n
が「改行」として動作してしまう!
r""
を付けると、\
を特別な意味を持たない「そのままの文字」として扱う ことができます。
ONEDRIVE_PATH = os.path.expanduser(“~/OneDrive/Backups”)
os.makedirs(GOOGLE_DRIVE_PATH, exist_ok=True)
答え:
os.makedirs() | 指定したフォルダを作成する |
exist_ok=True | フォルダが既に存在していてもエラーにしない |
このコードは、Pythonの os
(オペレーティングシステム) モジュールを使ってファイルやディレクトリの操作ができる。
os.makedirs()
の基本形
pythonコピーする編集するos.makedirs("フォルダ名")
📌 指定したフォルダを作成する。
📌 ただし、すでにフォルダがあるとエラーになる!
exist_ok=True
とは?
os.makedirs(GOOGLE_DRIVE_PATH, exist_ok=True)
Code language: PHP (php)
📌 フォルダが存在していてもエラーを出さない ようにするオプション。
📌 すでに Backups フォルダがあっても、エラーにならずにスクリプトが進む。
os.makedirs() の動作イメージ
例①: フォルダがない場合
もし C:\Users\hiroyuki\Google ドライブ\Backups
フォルダがなかった場合、
os.makedirs(GOOGLE_DRIVE_PATH, exist_ok=True)
✅ 新しくフォルダが作成される
例②: フォルダがすでにある場合
Backups
フォルダが すでに存在している 状態でスクリプトを実行
📌 何も起こらず、エラーも出ない!
✅ exist_ok=True
のおかげで、すでにフォルダがあるときはそのままスルーされる。
os.path.join
答え:引数に渡した文字列を結合し、1つのパスにすることが出来ます。
print(os.path.join(os.path.expanduser("~"), "AppData", "Roaming", "Code", "User"))
Code language: PHP (php)
出力:
C:\Users\ユーザー名\AppData\Roaming\Code\User
os.path.expanduser(path)
答え:os.path.expanduser("~")
は、「~」をユーザーのホームフォルダのパスに変換する関数 です。
✅ Windowsなら C:\Users\あなたのユーザー名
✅ Mac/Linuxなら /home/あなたのユーザー名
os.path.exists(path)
実在しているパスか確認
import shutil
ファイル・フォルダ操作(コピー・削除・移動)
shutil.rmtree
Pythonでファイルを削除するにはos.remove()
、ディレクトリ(フォルダ)を中のファイルやサブディレクトリごとすべて削除するにはshutil.rmtree()
を使う。空のディレクトリのみを削除対象とするos.rmdir()
, os.removedirs()
もある。
shutil.copytree
関数 | コピー対象 | メタデータ(タイムスタンプなど) |
---|---|---|
shutil.copy() | ファイルのみ | 保持しない(更新日時が変わる) |
shutil.copy2() | ファイルのみ | 保持する(元のタイムスタンプを維持) |
shutil.copytree() | フォルダ全体 | フォルダごとコピー(copy2() を使用) |
ここで書かれているこのコード
if os.path.exists(VSCODE_BACKUP_PATH):
shutil.rmtree(VSCODE_BACKUP_PATH) # 既存フォルダを削除
shutil.copytree(VSCODE_CONFIG, VSCODE_BACKUP_PATH) # 最新データをコピー
訳すと
もし VSCODE_BACKUP_PATH
(バックアップフォルダ)がすでに存在しているなら、フォルダごと削除せよその後、VSCODE_CONFIG
(VSCodeの設定フォルダ)を VSCODE_BACKUP_PATH
にコピーせよ
subprocessライブラリ
Pythonの標準ライブラリで、Pythonから他のプログラムやコマンドを実行するためのモジュールです。 例えば、コンピュータ内に保存されているファイルのリストを表示するコマンドや、特定のファイルを開くプログラムなどを、Pythonから直接呼び出して実行することができます。
subprocess.run(f"code.cmd --list-extensions > \"{VSCODE_EXTENSIONS_FILE}\"", shell=True) の詳細解説
このコードは VSCodeの拡張機能の一覧を取得し、指定したファイルに保存する ためのものです。
部分 | 説明 |
---|
subprocess.run(...) | 外部コマンドを実行する Pythonの関数 |
f"..." | f文字列(変数を埋め込める) |
"code.cmd --list-extensions" | VSCodeの拡張機能一覧を取得するコマンド |
> \"{VSCODE_EXTENSIONS_FILE}\" | 結果をファイルに保存(リダイレクト) |
shell=True | コマンドをシェル(cmd.exe)で実行 |
shell=True
の意味
subprocess.run(..., shell=True)
shell=True
を指定すると、コマンドプロンプト(cmd.exe)上で実行される>
(リダイレクト)を使うために必要- ただし、セキュリティ上のリスクがあるため、ユーザー入力を含める場合は使わないほうが良い
コード | 説明 |
---|
code.cmd --list-extensions | VSCodeの拡張機能一覧を取得 |
> "ファイル名" | 取得したリストをファイルに保存 |
subprocess.run(..., shell=True) | シェルで実行(リダイレクトを使うため) |
このコードを見てどうして保存されるのかわからなかったのだが「>
“ファイル名”」で保存だとは聞いてみないとわからないことだった。
コメント