跳至内容

如何通过命令行在 Mac 上自动截图

使用 macOS screencapture 循环进行全屏、固定区域和翻页截图,包含安全的文件命名和故障排查。

8 分钟阅读效率作者:Temposhot Team

每台 Mac 都自带 screencapture,这是系统截图快捷键背后的命令。在 zsh 循环中调用它,无需额外软件即可按固定间隔截取全屏或固定区域。本文逐步构建该循环,加入翻页功能,并列出最常见故障的解决方法。

在调试命令前检查权限

screencapture 以启动它的应用的权限运行。在 Terminal 中,这意味着 Terminal 需要屏幕录制权限。没有该权限时,命令仍会成功返回,但图片只显示壁纸和菜单栏。

打开 System Settings,进入 Privacy and Security,在屏幕录制列表中开启终端应用(Terminal、iTerm 或其他应用)。该项名称因 macOS 版本而异。更改后需退出并重新打开终端应用。

用测试截图确认权限

测试截图可以显示 macOS 是否允许终端读取屏幕。打开多个窗口后截图,然后打开文件。如果图片中显示了窗口,说明权限已生效。如果只显示壁纸和菜单栏,说明权限缺失,或更改后没有重新打开终端。

包含四项检查的清单:终端应用已在屏幕录制中开启,终端已退出并重新打开,测试图片显示了打开的窗口,测试图片可在 Preview 中打开。

测试完成后删除测试文件。它是全屏图片,可能包含隐私内容。

在 Terminal 中截一张图

编写循环前,先截取一张图:

screencapture -x ~/Desktop/test.png
open ~/Desktop/test.png

-x 参数关闭快门声音。如果图片中显示了打开的窗口,说明权限和路径都正常。运行 man screencapture 可查看当前 macOS 版本支持的全部参数。

本文使用的参数

包含七个 screencapture 参数及其作用的设置列表:关闭快门声音、仅截取主显示器、截取显示器 2、保存为 JPG、矩形区域、包含指针以及 5 秒延迟。

参数区分大小写。-c 将图片复制到剪贴板,-C 则将指针添加到图片中。多个参数需分开书写,例如 screencapture -x -m -t jpg file.jpg。

-T 延迟作用于每次 screencapture 命令执行之前。在循环中,它会为每一帧都增加延迟。如果只需延迟一次,请在循环中使用 sleep。

每隔几秒截取一次全屏

下面的循环以 3 秒为间隔截取 20 张图,并保存到以开始时间命名的新文件夹中:

#!/bin/zsh
out=~/Captures/run-$(date +%Y%m%d-%H%M%S)
mkdir -p "$out"

for i in {1..20}; do
  screencapture -x -m "$out/frame-$(printf %04d $i).png"
  sleep 3
done
echo "Saved 20 frames to $out"

补零的文件名(frame-0001.png)可使文件在访达和任何按名称排序的工具中保持截取顺序。-m 参数将截图限制为主显示器。若不加该参数,连接两台显示器的 Mac 会要求每个显示器对应一个文件名。如需改为截取副显示器,使用 -D 2。

将脚本保存为 capture.sh,运行 chmod +x capture.sh,然后执行 ./capture.sh。按 Control+C 可提前停止。已保存的帧会保留在文件夹中。

计算运行时长

循环在每次截图后都会 sleep,包括最后一次。因此 20 帧的运行总共会 sleep 60 秒。每次截图也需要少量时间,所以实际运行时间会略长于 sleep 的总和。下方时间线未计入截图耗时。

20 帧循环的时间线:第 1 帧在 0:00,第 2 帧在 0:03,第 20 帧在 0:57,循环结束后的汇总行在 1:00 输出。
20 帧示例的三个数值:每次运行 20 帧,每次运行 60 秒 sleep 时间,帧与帧之间间隔 3 秒。

要按时长设定运行,用时长除以间隔。若 10 分钟的运行每 5 秒截取一帧,需要用 600 除以 5,即 120 帧。将循环次数设为 120,sleep 设为 5:

for i in {1..120}; do
  screencapture -x -m "$out/frame-$(printf %04d $i).png"
  sleep 5
done

如果一次截图耗时 0.2 秒,120 次截图额外增加 24 秒,因此运行时间约为 624 秒。用 time screencapture -x ~/Desktop/timing.png 测量本机的截图耗时,然后删除测试文件。

按步骤名称为帧命名以便后续搜索

文件名中包含步骤名,运行结束后更容易查找帧。遍历同一 $out 文件夹中的步骤名列表:

steps=(login dashboard export)
for s in $steps; do
  screencapture -x -m "$out/$s.png"
  sleep 2
done

每个任务也应使用单独的文件夹。文件夹名中的时间戳表示运行开始的时间,任务名表示运行的内容。例如 Captures/onboarding-run-20261103-101500 可以区分同一天的两次运行,无需逐个打开文件即可找到某次运行。

文件名不含空格,可避免 shell 中的引号问题。当截取顺序重要而步骤名不重要时,保留补零的编号。

干净地停止循环

Control+C 会立即结束循环。已保存的帧保留在文件夹中,但脚本不输出汇总信息。在循环上方添加 trap,可在收到中断信号时输出帧数:

trap 'echo "Stopped after $i frames"; exit 0' INT

INT 是 Control+C 发送的信号。trap 在收到信号时读取 $i,因此报告的是最后开始的帧编号。在截图过程中停止,可能使最新的文件不完整。在用 PDF 工具打开文件夹之前,删除该文件,或将其大小与之前的帧进行比较。

对固定区域重复截图

添加 -R x,y,w,h 可截取一个矩形区域。数值单位为点,以主显示器的左上角为原点:

screencapture -x -R 200,120,1200,800 "$out/frame-$(printf %04d $i).png"

要确定坐标,按 Shift+Command+4,观察十字光标在区域左上角和右下角处旁边的数字。宽度为右边缘减左边缘,高度为下边缘减上边缘。下表列出了本节使用的按键。

包含三个按键的快捷键列表:Shift+Command+4 显示带坐标的十字光标,Shift+Command+3 将全屏文件保存到桌面,Control+C 停止正在运行的循环。

固定矩形不会跟随窗口。如果运行期间窗口移动或显示器排列发生变化,之后的帧会截取到错误的区域。

Retina 显示屏上的点与像素换算

-R 的数值单位为点,但保存的文件是像素。在 Retina 显示屏上,每个点在两个方向上各对应两个像素,因此 1200 × 800 点的矩形会保存为 2400 × 1600 像素的图片。缩放设置会改变倍数,因此应测量已保存的帧,而不是假定某个数值:

sips -g pixelWidth -g pixelHeight "$out/frame-0001.png"

下面的对比展示了两个区域在 2x 显示器和 1x 显示器上保存的尺寸。

两个 -R 区域在 2x 显示器和 1x 显示器上各自保存的像素尺寸对比。

基于像素的裁剪或设计规范需要像素值。按点规划的截图,-R 需要填写点值。混用两种单位会导致帧比预期的版面更大或更小。

保存 JPG 而非 PNG

使用 -t jpg 并修改扩展名:

screencapture -x -t jpg "$out/frame-$(printf %04d $i).jpg"

PNG 能保持文字边缘清晰,是界面截图更安全的默认选择。JPG 文件更小,对于包含数百帧的运行更有意义。该命令也接受 pdf 和 tiff。

为长时间运行选择格式

运行 500 帧会按所选格式生成 500 个文件。当文件夹大小比文字边缘清晰度更重要时选择 JPG;当读者需要放大查看小标签时选择 PNG。在脚本中显式传入 -t png,使格式在代码中可见。

PNG 与 JPG 输出在 screencapture 循环中的对比,涵盖文字边缘、文件大小以及各格式适用的运行类型。

长运行前先测量每种格式的一帧。对该文件运行 du -h,然后将文件大小乘以帧数,估算文件夹的总大小。

在截图之间按键而不超出目标

翻阅幻灯片或阅读器页面时,需要在每次截图后按一次键。osascript 通过 System Events 发送按键。键码 124 为右方向键:

pages=30
for i in {1..$pages}; do
  screencapture -x -m "$out/page-$(printf %04d $i).png"
  if (( i < pages )); then
    osascript -e 'tell application "System Events" to key code 124'
    sleep 1.5
  fi
done

三个细节可防止漏页或多页。截图先执行,因此起始页会被保存。if 语句跳过最后一次截图后的按键,阅读器不会翻过最后一页。按键后的 sleep 让下一页有时间渲染完成,再进行下一次截图。

System Events 将按键发送给最前面的应用,因此应在循环开始前点击阅读器窗口,或在顶部添加 sleep 5,以便切换应用。Terminal 需要辅助功能权限才能发送按键事件。

翻页使用的键码

osascript 通过 macOS 虚拟键码识别按键,而不是按输入的字符。下列键码涵盖翻页和确认时最常用的按键:

按键键码
左方向键123
右方向键124
下方向键125
上方向键126
空格49
回车36

部分阅读器只有在特定控件获得焦点时才翻页。正式长时间运行前,先用 3 页的运行测试按键,并检查每一页是否都发生了变化。

调整截图与按键的顺序

循环内的顺序决定每一帧显示哪一页。本节的循环先截图,再按键。下图展示了一个循环周期。

四步循环:截取当前页,发送右方向键,等待 1.5 秒,然后截取下一页。

如果先按键,每一帧都会显示屏幕上当前页的下一页,并且第一页永远不会被保存。

按键后的 sleep 决定节奏。从本地文件渲染的页面通常能在本文所用的 1.5 秒 sleep 内完成。通过网络加载图片的阅读器,某些页面可能需要 3 到 5 秒。应检查文档中最慢的页面,而不是第一页,因为包含大量图片的页面决定了最短等待时间。

以下两项检查可在长时间运行前发现大多数翻页错误:

  • 运行 3 页并打开这 3 帧。每一帧都必须显示不同的页面,且顺序正确。
  • 将最后一帧与文档的最后一页进行比较。如果最后一帧重复了某一页,说明按键多按了一次,或 sleep 时间不足。

保持长时间运行期间 Mac 唤醒

显示器休眠时,帧会呈现为黑色。用 caffeinate 包裹脚本,它会在脚本运行期间保持睡眠断言:

caffeinate -di ./capture.sh

-d 参数使显示器保持唤醒,-i 阻止空闲睡眠。caffeinate 使 Mac 保持唤醒,但不会使屏幕保持解锁。屏幕锁定期间截取的帧会显示锁屏界面,而不是应用。若 MacBook 在接通电源时合上盖子仍需保持唤醒,添加 -s。caffeinate 的 man 手册说明,该参数仅在 Mac 使用交流电源时生效。

长时间 screencapture 运行的正确与错误做法列表:在脚本前加上 caffeinate -di 启动,保持显示器开启,不要假定合上盖子后仍会持续截图,不要将 caffeinate 用作停止条件。

排查 screencapture 循环故障

现象原因解决方法
只显示壁纸和菜单栏缺少屏幕录制权限允许终端应用,然后重新打开
"No such file or directory"输出文件夹不存在在循环前运行 mkdir -p
每次截图出现两张图片或一个错误多个显示器,但只有一个文件名添加 -m 或 -D 1
黑色帧显示器已休眠使用 caffeinate -di 运行脚本
跳页按键早于页面渲染完成发送增加按键后的 sleep
按键被忽略缺少辅助功能权限,或最前端的应用不正确允许终端应用,并点击目标窗口

检查输出文件夹

运行结束后,每次运行生成一个文件夹,帧文件名按截取顺序排列。下方的目录树展示了一次从 2026 年 11 月 3 日 10:15:00 开始、包含四帧的运行。第 5 至第 20 帧遵循相同的规则。

一次已完成的 screencapture 运行的文件树:Captures 文件夹中包含一个运行文件夹,内有四张编号的 PNG 帧。

诊断帧内容完全相同的问题

如果每一帧显示的内容都相同,请按以下顺序检查原因:

  1. 目标在两次截图之间没有变化。循环保存的是屏幕上当前显示的内容,因此不翻页的页面或保持打开的对话框会产生相同的帧。应增加按键或延长等待时间。
  2. 其他窗口遮挡了目标。-R 和 -m 截取的是屏幕区域,而不是窗口背后的内容。将目标窗口移到最前,并在整个运行期间保持其位置。
  3. 间隔短于内容变化的周期。每 10 秒才移动一次的进度条,在 1 秒间隔下看起来是静止的。在修改循环之前,先以更长的间隔检查各帧。

如果不确定两个文件是否相同,用 shasum -a 256 比较首尾两帧。哈希值相同即可确认像素完全相同。

每次运行后统计文件数。20 帧的运行应生成 20 个文件。数量更少,说明循环提前停止,或某次截图失败,失败信息显示在终端中。

当脚本不再是简单选择时

Shell 循环适合以相同方式重复执行的固定任务。每个新需求都会增加代码,例如在某个时钟时间停止、暂停并恢复、按名称选择窗口(-l 参数需要窗口 ID,而 macOS 不会列出窗口 ID),或生成可搜索的 PDF。

Temposhot 的 Auto Capture 将这些需求转化为设置。可从缩略图中选择 Screens、Windows 或 Custom Area,将 Screenshots、Duration 或 End time 设为停止条件,并在 Key press 字段中录制任意按键。浮动工具栏可以暂停、继续和结束运行。导出格式包括 PNG、JPG、ZIP、可搜索的 PDF、MP4 和 GIF。仅当 Mac 安装了 WebP 编码器时,才会显示 WebP。

将脚本选项映射到设置

脚本中的每个决定都有对应的 Auto Capture 设置。以下步骤在 Temposhot 中重建翻页循环:

在 Auto Capture 中的四个设置步骤:选择来源,设置停止条件和间隔,在 Key press 字段中录制 Right Arrow,然后设置倒计时并开始运行。

切换之前,先确定脚本中哪些部分仍然需要。Auto Capture 覆盖常见情况:对单个显示器、单个窗口或单个矩形进行定时系列截图,并可在帧之间选择性地按键。它不能在两次截图之间运行任意 shell 命令,因此包含自定义逻辑的脚本(例如根据电子表格重命名文件)仍应保留在 shell 中。

本文示例的对应关系如下:

  • 20 帧循环,sleep 3 秒,对应 Screenshots 停止条件设为 20,间隔设为 3 秒。
  • 10 分钟的运行,每 5 秒一帧,对应 Duration 停止条件设为 10 分钟,间隔设为 5 秒。Duration 和 End time 要求间隔大于零。
  • 翻页循环对应 Key press 设为 Right Arrow,间隔设为 1.5 秒。Key press 是 Pro 功能,需要辅助功能权限。
  • 固定矩形对应 Custom Area。拖动矩形,直到覆盖层显示所需的宽度和高度。

免费版限制每次会话的截图数量。需要更多帧的运行须使用 Temposhot Pro。

有两个设置通常与脚本默认值不同。倒计时默认为 3 秒,可用于在开始前将页面调整到起始状态。当目标在点击开始后需要更多时间加载时,设为 5 秒或 10 秒。间隔默认为 1 秒,因此每次运行都应显式设置。

固定任务保留脚本

当任务固定,且相同命令需要在每台机器上运行时,使用脚本。例如,由 cron 任务启动的本地仪表盘夜间截图。脚本也便于纳入版本控制,可以记录每次对时间或区域的修改。

Temposhot 会话适合由人工操作、在屏幕前观察、遇到问题时暂停、并希望直接在应用中获得结果的任务。两者都可以生成相同的帧。区别在于由谁维护指令:脚本保存在文件中,Auto Capture 设置保存在应用中,并沿用已保存的默认值。

常见问题

screencapture 将文件保存到哪里?

文件保存到最后一个参数指定的路径。使用 -c 时,图片会改为复制到剪贴板。

screencapture 能包含指针吗?

可以。添加 -C 即可包含指针。它仅适用于非交互式截图,本文中的所有命令均属此类。

如何在第一次截图前添加延迟?

对单次截图使用 -T 5,延迟 5 秒;或在循环前添加 sleep 5。

能将帧转换为 PDF 或视频吗?

可以。Image to PDF 可按文件名顺序将帧合并为一个 PDF,Images to Video 可将其转换为视频。两者都在浏览器中运行,文件保留在本机上。

screencapture 能只截取一个窗口吗?

可以,使用 -l 加数字窗口 ID。Terminal 不列出窗口 ID,因此 ID 需要通过其他工具获取。Auto Capture 的 Windows 标签页则可以从缩略图中选择窗口。

为什么第 9999 帧之后帧会乱序?

%04d 格式至少输出四位数字。从第 10000 帧开始,frame-10000.png 这类文件名会在按名称排序时排在 frame-9999.png 之前。超过 9999 帧的运行应使用 %05d。

Control+C 之后帧会保留吗?

会。中断前保存的帧保留在文件夹中。上文一节中的 trap 会在脚本停止时输出帧数。

将可重复的截图转化为成品

当脚本超出固定区域和固定数量的范围时,请改用 Auto Capture。自动截取指南介绍了所有选项,下载页面提供 Apple Silicon 版本。

command-linescreencapturezshscreenshot-automation

本文使用的术语: retina screenshot, screenshot automation, screenshot timer

把重复性截图整理为成品

Temposhot 可按定时或每次点击进行截图,并将结果导出为 PDF、图片、ZIP 或 MP4。

相关文章