Google Takeoutの写真・動画だけをまとめたい ― PowerShellでOutフォルダーへ自動整理する

PowerShellカテゴリを表すパンダのイラスト PowerShell

この記事について
この記事は、生成AIを活用し、実際にWindows PowerShell 5.1で試した結果をもとに整理しています。机上のサンプルではなく、Google Takeoutの実データでエラーを直しながら動作確認したスクリプトです。

検証ステータス:✅ Windows PowerShell 5.1 実機動作確認済み
画像2,645件、動画104件、合計2,749件・15.81GBを検出し、修正版v4でコピー処理と進捗表示が動くことを確認しています。

Google Takeoutで写真をバックアップすると、ZIP、展開済みフォルダー、JSONなどが混ざっていて、あとから「写真と動画だけ1か所に集めたい」と思うことがあります。

手作業でもできますが、数千件になると確認だけでも大変です。

そこで今回は、画像は Out\Images、動画は Out\Videos に自動で集めるPowerShellを作りました。

ポイントは、単にコピーするだけではなく、あと何件あるか、何GB終わったか、残り時間の目安まで見えることです。大きな動画を処理している途中でも「固まった?」と感じにくいようにしています。

まず、どう使うのか

使い方はできるだけ単純にしました。

Google TakeoutのZIPや展開済みフォルダーがある場所に、今回のスクリプトを置きます。

GoogleTakeout
├─ takeout-001.zip
├─ takeout-002.zip
├─ takeout-003
│  └─ Takeout
│     └─ Google フォト
└─ Collect-GoogleTakeoutMedia-v4-beginner.ps1

そのフォルダーでPowerShellを開き、次を実行します。

.\Collect-GoogleTakeoutMedia-v4-beginner.ps1

基本操作はこれだけです。

実行すると、自動で Out が作られます。

GoogleTakeout
├─ takeout-001.zip
├─ takeout-002.zip
├─ takeout-003
├─ Collect-GoogleTakeoutMedia-v4-beginner.ps1
│
└─ Out
   ├─ Images     ← 写真・画像
   ├─ Videos     ← 動画
   └─ media-copy-YYYYMMDD-HHMMSS.log
                  ↑ エラーなどの記録

処理は大きく3段階

コードを見る前に、処理の流れだけ分かれば十分です。

flowchart TD
    A[Google Takeoutのフォルダー] --> B[STEP 1 普通のフォルダーを調べる]
    B --> C[STEP 2 ZIPの中を調べる]
    C --> D[画像・動画の全件数と容量を集計]
    D --> E[STEP 3 Outへコピー]
    E --> F[Images]
    E --> G[Videos]
    E --> H[ログ]

STEP 1:普通のフォルダーを調べる

まず、展開済みのGoogle Takeoutフォルダーを順番に調べます。

ここではまだコピーしません。

.jpg.png.heic などは画像、.mp4.mov などは動画として一覧に記録します。Google Takeoutに付いてくるJSONなどは対象外です。

考え方は単純で、ファイル名の最後の「拡張子」を見ています。

$ImageExtensions = @(
    '.jpg','.jpeg','.png','.gif','.bmp','.tif','.tiff','.webp',
    '.heic','.heif','.avif'
)

$VideoExtensions = @(
    '.mp4','.mov','.m4v','.avi','.mkv','.webm',
    '.3gp','.mts','.m2ts','.mpg','.mpeg','.wmv'
)

初心者向けに言えば、これは「画像として扱う拡張子一覧」「動画として扱う拡張子一覧」を先に作っているだけです。

STEP 2:ZIPは全部展開せず、中身だけ見る

Google TakeoutはZIPのまま残っていることもあります。

今回のスクリプトでは、ZIPを全部展開してから探すのではなく、PowerShellから.NETのZIP機能を使って中身を直接確認します。

Add-Type -AssemblyName System.IO.Compression.FileSystem
$archive = [System.IO.Compression.ZipFile]::OpenRead($zipPath)

そして、ZIPの中に画像・動画があれば、あとで必要なものだけ取り出します。

これなら、ZIPを丸ごと展開するための余分な空き容量を減らせます。

さらに、

takeout-001.zip
takeout-001\

のようにZIPと同名の展開済みフォルダーが両方ある場合は、ZIP側をスキップします。同じ写真を二重に集めるのを避けるためです。

全体で何件あるかを先に出す

検索が終わると、実際のコピー前に全体像を表示します。

今回の実機確認では次の結果になりました。

--- 検索結果 ---
画像 : 2,645 件
動画 :   104 件
合計 : 2,749 件 / 15.81 GB

これがあると、「何千件あるのか分からない処理を待つ」のではなく、最初にゴールの大きさが分かります

STEP 3:Outへコピーする

ここから実際のコピーです。

画像なら、

Out\Images

動画なら、

Out\Videos

へ保存します。

ただし、大きな動画を一気にコピーするのではなく、4MiBずつ読み書きします。

$buffer = New-Object byte[] 4194304

while (($read = $InputStream.Read($buffer, 0, $buffer.Length)) -gt 0) {
    $outStream.Write($buffer, 0, $read)
    $script:ProcessedBytes += $read
    Show-CopyProgress -CurrentName $DisplayName
}

ここが「固まって見えない」ためのポイントです。

大きなファイルの途中でも処理済み容量が増えるため、進捗を更新できます。

「あとどれくらい?」を表示する

コピー中は、次のような情報が分かるようにしています。

1200/2749 完了
残り 1549 件
6.8 GB / 15.81 GB
残り目安 18分

単純に「1200件終わった」だけではありません。

画像は数MBでも、動画は数GBということがあります。そのため、件数だけではなく処理済み容量から残り時間を概算します。

これは大量ファイルを扱う事務作業でも使いやすい考え方です。

コピー途中のファイルには .part を付ける

安全面で入れたのが .part です。

たとえば動画をコピーするとき、いきなり

movie.mp4

を作りません。

まず、

movie.mp4.part

としてコピーします。

最後まで正常にコピーできたときだけ、

movie.mp4

へ変更します。

$partPath = $Destination + '.part'

# コピー処理


# ...

Move-Item -LiteralPath $partPath -Destination $Destination -Force

途中で止まった動画を、完成した動画と間違えにくくするためです。

元のGoogle Takeoutデータは削除しません。

同じ名前の写真があっても上書きしない

別々のフォルダーに、同じ IMG_0001.JPG があることも考えられます。

同名・同サイズなら、すでにコピー済みとみなしてスキップします。

同名でもサイズが違う場合は、

IMG_0001__a1b2c3d4.JPG

のように短い識別文字を付けて別ファイルとして保存します。

「とにかく1つのフォルダーに集めたい」という処理では、上書きしないことが大事です。

実際に動かしたら、15GBで一度エラーになった

ここは今回、実際に動かしたから分かった部分です。

最初の版では15.81GBの総容量を使って残り容量を計算したところ、Windows PowerShell 5.1で次のようなエラーが出ました。

Int32 型の値が大きすぎるか、または小さすぎます。

原因は、大きなバイト数を32bit整数として扱おうとしたことでした。

そこで修正版では、容量を明示的に64bit整数の [long] として扱っています。

[long]$remainingBytes = $script:TotalBytes - $script:ProcessedBytes
if ($remainingBytes -lt 0) {
    $remainingBytes = 0L
}

これは小さなサンプルデータでは気付きにくいところです。

数GBでは動いても、実データ15GBで初めて落ちる。

今回の記事で一番「実際に試した意味」があるのは、この部分かもしれません。

コード全部を理解しなくても使える

PowerShell初心者から見ると、FileStreamArrayListZipFile など見慣れない言葉が出てきます。

でも、最初は全部を理解する必要はありません。

今回の完全版スクリプトには、処理を次の8つに分けて、日本語コメントを入れています。

  1. 最初の設定

  2. 写真か動画かを判断する準備

  3. 進み具合を覚えておく数字

  4. 1ファイルをコピーする部品

  5. STEP 1:フォルダーを調べる

  6. STEP 2:ZIPを調べる

  7. STEP 3:実際にコピーする

  8. 最後に結果を表示する

まずは、

置く
 ↓
実行する
 ↓
中を調べる
 ↓
件数を数える
 ↓
Outへコピーする
 ↓
結果を見る

この流れが分かれば十分です。

ZIPを調べたくない場合

展開済みフォルダーだけを処理したい場合は、-NoZip を付けます。

.\Collect-GoogleTakeoutMedia-v4-beginner.ps1 -NoZip

別の場所を指定することもできます。

.\Collect-GoogleTakeoutMedia-v4-beginner.ps1 `
    -SourceRoot "D:\GoogleTakeout"

まとめ

今回やりたかったことは、技術的には「再帰検索」「ZIP読込」「ストリームコピー」ですが、利用者から見るともっと単純です。

Google Takeoutの中から写真と動画だけを集めたい。処理が止まっていないか分かりたい。あとどれくらいか知りたい。

そのために必要な機能をPowerShellへ順番に足していきました。

そして今回は、実際に2,749件・15.81GBのデータで試したことで、PowerShell 5.1の大容量数値エラーまで見つかり、修正版v4で動作確認できました。

「コードを書く」だけで終わらず、実データで動かして、出たエラーを直して、初心者が使える形にするところまで含めて1つのサンプルです。

文書情報

記事タイトル
Google Takeoutの写真・動画だけをまとめたい ― PowerShellでOutフォルダーへ自動整理する
作成日
更新日
Source URL
https://papanda925.com/?p=15471

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました