この記事について
この記事は、生成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初心者から見ると、FileStream、ArrayList、ZipFile など見慣れない言葉が出てきます。
でも、最初は全部を理解する必要はありません。
今回の完全版スクリプトには、処理を次の8つに分けて、日本語コメントを入れています。
最初の設定
写真か動画かを判断する準備
進み具合を覚えておく数字
1ファイルをコピーする部品
STEP 1:フォルダーを調べる
STEP 2:ZIPを調べる
STEP 3:実際にコピーする
最後に結果を表示する
まずは、
置く ↓ 実行する ↓ 中を調べる ↓ 件数を数える ↓ 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つのサンプルです。

