只想整理 Google Takeout 的照片和视频?用 PowerShell 自动归类到 Out 文件夹

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

关于本文
本文结合了生成式 AI 的辅助,并基于在 Windows PowerShell 5.1 上的实际测试结果整理而成。这不是纸上谈兵的示例,而是在使用 Google Takeout 真实数据并修复报错的过程中验证过的脚本。

验证状态:✅ 已在 Windows PowerShell 5.1 真机上验证通过
已成功检测到 2645 张图片、104 个视频,共计 2749 个文件、15.81 GB,并确认修正版 v4 的复制处理与进度显示功能运行正常。

使用 Google Takeout 备份照片时,里面会混杂着 ZIP 压缩包、已解压的文件夹、JSON 文件等,有时我们事后会希望能“把照片和视频单独收集到一个地方”。

虽然也可以手动完成,但如果有数千个文件,光是检查就够让人头疼了。

因此,这次我们制作了一个 PowerShell 脚本,能够:自动将图片收集到 OutImages,视频收集到 OutVideos

它的核心亮点在于,不仅是简单地复制,还能:显示还剩多少个文件、已经处理了多少 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
                  ↑ エラーなどの記録

处理过程大致分为三个阶段

在看代码之前,只要了解处理流程就足够了。

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[ログ]

步骤 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'
)

对初学者来说,这就相当于预先制作好了:“作为图片处理的扩展名列表”和“作为视频处理的扩展名列表”

步骤 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

有了这个,就不用面对“不知道还有几千个文件”的未知等待,而是能:在一开始就知道目标有多大

步骤 3:复制到 Out 文件夹

接下来就是实际的复制操作了。

如果是图片,保存到:

OutImages

如果是视频,保存到:

OutVideos

不过,脚本不会一口气复制大视频,而是以 4 MiB 为单位进行读写。

$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

那样附加简短的识别字符,作为独立文件保存。

在“无论如何都要收集到一个文件夹中”的任务里,不进行覆盖是非常重要的。

实际运行后,在 15GB 时遇到了报错

这是只有在实际运行后才能发现的部分。

在最初的版本中,由于使用 15.81 GB 的总容量来计算剩余容量,导致 Windows PowerShell 5.1 报了以下错误。

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

原因在于试图将庞大的字节数当作 32 位整数来处理。

因此,在修正版中,容量被明确作为 64 位整数 [long] 来处理。

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

这一点在小型示例数据中是很难察觉的。

处理几 GB 时运行正常,但在处理 15 GB 的真实数据时才会崩溃。

本文中“实际尝试的价值”最大的地方,可能就在于此。

无需完全理解代码即可使用

对于 PowerShell 初学者来说,可能会看到 FileStreamArrayListZipFile 等生疏的词汇。

但一开始并不需要全部理解。

本次提供的完整版脚本将处理过程分为以下 8 个部分,并添加了中文注释。

  1. 初始设置

  2. 判断是照片还是视频的准备工作

  3. 记录进度的数字变量

  4. 复制单个文件的组件

  5. 步骤 1:检查文件夹

  6. 步骤 2:检查 ZIP 文件

  7. 步骤 3:实际执行复制

  8. 最后显示结果

首先,

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

只要明白这个流程就足够了。

如果不希望检查 ZIP 文件

如果只想处理已解压的文件夹,可以加上 -NoZip 参数。

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

也可以指定其他路径。

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

总结

这次想做的事情,从技术上讲是“递归搜索”、“ZIP 读取”和“流复制”,但对使用者而言要简单得多。

只想把 Google Takeout 里的照片和视频收集起来。想知道处理有没有卡住。想知道还要多久才能完成。

为此,我们逐步向 PowerShell 中添加了所需的功能。

通过这次使用 2749 个文件、15.81 GB 的真实数据进行测试,我们甚至发现了 PowerShell 5.1 的大数值整数错误,并在修正版 v4 中确认了运行正常。

不仅止步于“编写代码”,用真实数据运行、修复出现的错误、将其打造成初学者也能使用的形态,这整个过程才算是一个完整的示例。

文档信息

文章??
只想整理 Google Takeout 的照片和视频?用 PowerShell 自动归类到 Out 文件夹
?布日期
更新日期
来源
https://papanda925.com/?p=15473&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制