About This Article
This article is organized based on actual results tested in Windows PowerShell 5.1, leveraging generative AI. Rather than a theoretical sample, this script was debugged and verified using actual Google Takeout data.Verification Status: ✅ Verified on Real Hardware Running Windows PowerShell 5.1
Detecting 2,645 images and 104 videos (2,749 items and 15.81 GB in total), we confirmed that the copy process and progress display work correctly in the revised v4 version.
When backing up photos with Google Takeout, ZIP files, extracted folders, and JSON files are often mixed together, leaving you wanting to consolidate "only the photos and videos in one place" afterward.
While you can do this manually, verifying thousands of items is a daunting task.
Therefore, this time, we created a PowerShell script that automatically gathers:Images into OutImages and videos into OutVideos.
The key feature is that instead of simply copying, it displays how many items are left, how many gigabytes have been processed, and even an estimated time remaining.This ensures that even when processing large videos, you are less likely to feel like the script has frozen.
- First, How to Use It
- The Process in Three Main Steps
- STEP 2: Inspect ZIPs Without Fully Extracting Them
- Calculating the Total Number of Items First
- STEP 3: Copying to the Out Folder
- Displaying "How Much Time is Left?"
- Attaching .part to Files During Copying
- Original Google Takeout data is not deleted.
- Encountering an Error at 15 GB During Real-World Execution
- Usable Without Understanding All the Code
- When You Do Not Want to Inspect ZIP Files
- Conclusion
First, How to Use It
We made the usage as simple as possible.
Place this script in the location where your Google Takeout ZIP files or extracted folders are located.
GoogleTakeout ├─ takeout-001.zip ├─ takeout-002.zip ├─ takeout-003 │ └─ Takeout │ └─ Google フォト └─ Collect-GoogleTakeoutMedia-v4-beginner.ps1
Open PowerShell in that folder and run the following command.
.Collect-GoogleTakeoutMedia-v4-beginner.ps1
That is all the basic operation requires.
Running it will automatically create Out.
GoogleTakeout
├─ takeout-001.zip
├─ takeout-002.zip
├─ takeout-003
├─ Collect-GoogleTakeoutMedia-v4-beginner.ps1
│
└─ Out
├─ Images ← 写真・画像
├─ Videos ← 動画
└─ media-copy-YYYYMMDD-HHMMSS.log
↑ エラーなどの記録
The Process in Three Main Steps
Before looking at the code, understanding the flow of the process is all you need.
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: Examine Regular Folders
First, inspect the extracted Google Takeout folders one by one.
No copying is done at this stage.
.jpg、.png、.heicFiles like are recorded to the list as images, and files like are recorded as videos. JSON files included with Google Takeout are excluded..mp4、.mov
The concept is simple: it checks the "file extension" at the end of the filename.
$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'
)
For beginners, this simply means creating lists in advance of:"extensions to treat as images" and "extensions to treat as videos"
STEP 2: Inspect ZIPs Without Fully Extracting Them
Google Takeout data sometimes remains in ZIP archives.
In this script, instead of extracting ZIP files entirely before searching, we use .NET ZIP features via PowerShell to check their contents directly.
Add-Type -AssemblyName System.IO.Compression.FileSystem $archive = [System.IO.Compression.ZipFile]::OpenRead($zipPath)
Then, if there are images or videos inside the ZIP, we extract only the necessary items later.
This reduces the extra free disk space required to extract entire ZIP archives.
Furthermore, if both an extracted folder and a ZIP file with the same name exist, such as
takeout-001.zip takeout-001
, the ZIP file is skipped.This prevents duplicate collection of the same photos.
Calculating the Total Number of Items First
Once the search is complete, the overall picture is displayed before actual copying begins.
Our actual hardware verification yielded the following results.
--- 検索結果 --- 画像 : 2,645 件 動画 : 104 件 合計 : 2,749 件 / 15.81 GB
Instead of waiting blindly for a process of unknown size, you know the size of the goal right from the beginning.。
STEP 3: Copying to the Out Folder
This is where the actual copying takes place.
Images are saved to , and videos are saved to .
OutImages
OutVideos
However, rather than copying large videos all at once, they are read and written in 4 MiB chunks.
$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
}
This is the key to preventing the script from appearing frozen.
Because the processed capacity increases even in the middle of large files, progress updates can be shown.
Displaying "How Much Time is Left?"
During copying, information like the following is displayed.
1200/2749 完了 残り 1549 件 6.8 GB / 15.81 GB 残り目安 18分
It doesn't just say "1,200 items finished."
While images might be a few megabytes, videos can be several gigabytes. Therefore, the remaining time is estimated based on the processed data size rather than just the item count.
This approach is also easy to apply to routine administrative tasks involving large volumes of files.
Attaching .part to Files During Copying
is a safety measure we implemented..part
For instance, when copying a video, it does not immediately create
movie.mp4
.
It is first copied as
movie.mp4.part
.
Only when it has copied successfully to the very end is the extension changed to
movie.mp4
.
$partPath = $Destination + '.part' # コピー処理 # ... Move-Item -LiteralPath $partPath -Destination $Destination -Force
This prevents interrupted videos from being mistaken for successfully completed ones.
Original Google Takeout data is not deleted.
Not Overwriting Even If Photos Have the Same NameIMG_0001.JPGIt is possible that identical filenames exist across different folders, such as
.
If they have the same name and size, they are considered already copied and skipped.
IMG_0001__a1b2c3d4.JPG
If they have the same name but different sizes, they are saved as separate files with a short distinguishing identifier attached, like .
When performing a task where you simply want to "consolidate everything into a single folder," avoiding overwrites is crucial.
Encountering an Error at 15 GB During Real-World Execution
This was something we only discovered by running it in practice.
In the initial version, when calculating the remaining capacity using the total capacity of 15.81 GB, Windows PowerShell 5.1 threw the following error.
Int32 型の値が大きすぎるか、または小さすぎます。
The cause was attempting to treat a large byte count as a 32-bit integer.
Therefore, in the revised version, capacities are explicitly handled as 64-bit integers using [long].
[long]$remainingBytes = $script:TotalBytes - $script:ProcessedBytes
if ($remainingBytes -lt 0) {
$remainingBytes = 0L
}
This is something that is difficult to notice with small sample datasets.
It works fine for a few gigabytes, but fails for the first time on 15 GB of real data.
This part may be the most valuable reason for having "tried it out in practice" in this article.
Usable Without Understanding All the Code
From a PowerShell beginner's perspective, unfamiliar terms like appear.FileStream、ArrayList、ZipFile
However, you do not need to understand everything right away.
The complete script provided here divides the process into the following eight parts with Japanese comments included:
Initial settings
Preparation to determine whether an item is a photo or video
Counters to track progress
A module to copy a single file
STEP 1: Inspect folders
STEP 2: Inspect ZIP files
STEP 3: Perform actual copying
Display final results
For now, understanding this general flow is enough.
置く ↓ 実行する ↓ 中を調べる ↓ 件数を数える ↓ Outへコピーする ↓ 結果を見る
When You Do Not Want to Inspect ZIP Files
If you want to process only extracted folders, append -NoZip.
.Collect-GoogleTakeoutMedia-v4-beginner.ps1 -NoZip
You can also specify a different location.
.Collect-GoogleTakeoutMedia-v4-beginner.ps1 `
-SourceRoot "D:GoogleTakeout"
Conclusion
What we wanted to accomplish this time is technically "recursive searching," "ZIP reading," and "stream copying," but from a user's perspective, it is much simpler.
They want to gather only photos and videos from Google Takeout, know whether the process is hanging, and find out how much time is left.
We added the necessary functions to PowerShell step by step to achieve this.
By actually testing it with 2,749 items totaling 15.81 GB of data, we uncovered large numeric errors in PowerShell 5.1 and successfully verified operation using the revised v4 script.
It goes beyond just "writing code";running it on real data, fixing the errors that occur, and shaping it into a form that beginners can use constitute a complete, unified sample.
