AppleScript 实战

2024-03-19 王汪旺
Mac 编程 自动化

AppleScript 是 Apple 系统上专为自动化任务设计的脚本语言,它可以控制应用程序、操作文件、执行网络任务等。对于想要掌握这项技术的人来说,理解基本语法、如何与应用程序交互、如何调试代码及如何处理常见错误是至关重要的。

本教程将从最基础的语法入手,逐步深入,覆盖注意事项、最佳实践、多个详细案例等内容,帮助你掌握 AppleScript 技术。

目录

  1. AppleScript 基础概念
  2. 语法规则
  3. 变量和数据类型
  4. 控制结构
  5. 与应用程序交互
  6. 调试和错误处理
  7. 实际应用案例
  8. 进阶技巧与最佳实践

AppleScript 基础概念

AppleScript 的设计理念是“接近自然语言”,它的目的是让用户可以以类似英语的语法来与计算机进行交互。AppleScript 的操作对象包括文件、应用程序以及系统层面的任务。它能够有效地帮助用户简化重复的操作,特别是在自动化日常任务时,能够节省大量的时间。

主要概念

  • 应用程序:AppleScript 主要是通过 tell application​ 语句来控制应用程序的行为,启动程序、发送命令、获取信息等。
  • 对象:AppleScript 操作的“对象”不仅仅是应用程序,还包括文件、文件夹、窗口、文本等。
  • 命令和函数:AppleScript 包含了各种可以执行的命令和函数,通过 tell​ 和 do​ 语句来调用它们。
  • 脚本编辑器:苹果提供的脚本编辑器(AppleScript Editor 或 Script Editor)帮助你编写、调试和执行 AppleScript 脚本。

语法规则

AppleScript 语法接近英语,虽然没有严格的语言约束,但要编写出有效的脚本,理解其语法是非常重要的。下面是一些基本的语法规则。

1. 注释

注释是代码中用于解释的部分,不会被执行,常用于标明代码的用途或提醒自己注意某些事项。注释以 --​ 开头。

-- 这是一个注释,程序不会执行此行

2. 命令与表达式

AppleScript 中的命令通常是完整的动作,比如启动应用程序、创建文件等。命令末尾没有逗号或分号。

tell application "Finder"  -- 命令:告诉 Finder 执行操作
    activate  -- 启动 Finder 应用
end tell

3. 赋值

变量赋值通过 set​ 来完成,后面跟着变量名和要赋予的值。AppleScript 会自动推断变量类型。

set myVar to "Hello, World!"  -- 设置字符串
set myNumber to 42  -- 设置数字

4. 多行命令

如果一条命令非常长,可以使用换行符来分隔。例如,在 tell​ 块内可以继续执行多个命令:

tell application "Finder"
    activate
    set folderPath to (path to desktop) -- 获取桌面路径
end tell

5. 条件语句(if)

AppleScript 允许使用 if​ 来进行条件判断。

if someCondition is true then
    display dialog "Condition is true!"  -- 显示对话框
else
    display dialog "Condition is false."
end if

6. 循环语句(repeat)

AppleScript 支持使用 repeat​ 来循环执行某些操作。

repeat with i from 1 to 10
    display dialog "Iteration number " & i  -- 显示迭代数字
end repeat

变量和数据类型

AppleScript 支持多种数据类型,包括字符串、数字、日期、列表等。我们可以根据需要定义变量,并给变量赋不同的值。

1. 字符串

字符串通过双引号括起来。

set myString to "Hello, AppleScript!"  -- 字符串

2. 数字

AppleScript 可以处理整数和浮点数。

set myNumber to 42  -- 整数
set pi to 3.1415  -- 浮点数

3. 布尔值

布尔值只有 true​ 和 false​ 两种。

set isFinished to true
set isReady to false

4. 列表

列表用大括号 {}​ 包裹,元素之间用逗号分隔。

set myList to {1, 2, 3, "apple", "orange"}

5. 日期

日期表示当前系统时间或某个指定的时间。

set myDate to current date  -- 当前日期和时间
set futureDate to date "Friday, 24 October 2025 10:00:00"  -- 指定日期

控制结构

1. if 语句

AppleScript 支持常见的 if​ 条件判断。

if age > 18 then
    display dialog "Adult"  -- 成人
else
    display dialog "Minor"  -- 未成年
end if

2. repeat 循环

AppleScript 提供了多种类型的循环:

  • for 循环
repeat with i from 1 to 5
    display dialog "This is iteration " & i
end repeat
  • while 循环
set i to 1
repeat while i is less than 5
    display dialog "Counter: " & i
    set i to i + 1
end repeat

与应用程序交互

AppleScript 的强大之处在于它能够与系统中的各种应用程序进行交互。例如,我们可以通过 tell application​ 控制 Mac 上的程序。

1. 启动应用程序

tell application "Finder"
    activate  -- 激活 Finder 应用程序
end tell

2. 控制 Safari 打开网站

tell application "Safari"
    open location "http://www.apple.com"  -- 打开 URL
    activate  -- 启动 Safari
end tell

3. 发送邮件

发送邮件的正确脚本如下:

tell application "Mail"
    set newMessage to make new outgoing message with properties {subject:"Test Email", content:"This is a test email.", visible:true}
    tell newMessage
        make new to recipient with properties {address:"someone@example.com"}
    end tell
    send newMessage
end tell

调试和错误处理

1. 调试

你可以使用 log​ 来输出变量的值,帮助调试脚本。

log "Current value of myVar: " & myVar

2. 错误处理

AppleScript 提供了 try​ 和 on error​ 语句来处理错误,防止程序崩溃。

try
    -- 可能会发生错误的代码
    set myFile to open file "nonexistentFile.txt"
on error errMsg number errNum
    display dialog "Error: " & errMsg  -- 捕获错误
end try

实际应用案例

1. 自动整理桌面文件

tell application "Finder"
    set desktopFolder to desktop
    set fileList to files of desktopFolder

    repeat with aFile in fileList
        set fileExtension to name extension of aFile
        if fileExtension is "jpg" then
            move aFile to folder "Pictures" of desktopFolder
        else if fileExtension is "txt" then
            move aFile to folder "TextFiles" of desktopFolder
        end if
    end repeat
end tell

2. 批量重命名文件

tell application "Finder"
    set desktopFolder to desktop
    set fileList to files of desktopFolder

    repeat with aFile in fileList
        set fileName to name of aFile
        set newName to "new_" & fileName
        set name of aFile to newName

好的,我们继续扩展更多的案例和内容。


3. 自动备份文件夹

假设你有一个文件夹,想要定期备份到另一个文件夹中,可以用以下脚本实现:

tell application "Finder"
    set sourceFolder to folder "Documents" of home
    set backupFolder to folder "Backup" of home
    set fileList to files of sourceFolder

    -- 遍历文件并复制到备份文件夹
    repeat with aFile in fileList
        duplicate aFile to backupFolder
    end repeat
end tell

这个脚本会将 Documents​ 文件夹中的所有文件复制到 Backup​ 文件夹中。你可以根据需要修改文件夹路径,并通过 duplicate​ 命令实现文件的复制。


4. 查找并打开特定类型的文件

假设你希望打开桌面上所有的 .txt​ 文件,可以使用下面的脚本:

tell application "Finder"
    set desktopFolder to desktop
    set fileList to files of desktopFolder

    repeat with aFile in fileList
        set fileExtension to name extension of aFile
        if fileExtension is "txt" then
            open aFile  -- 打开文本文件
        end if
    end repeat
end tell

此脚本会查找桌面上所有扩展名为 .txt​ 的文件并打开它们。


5. 控制 iTunes 播放音乐

你可以使用 AppleScript 控制 iTunes 播放或暂停音乐,甚至切换曲目。例如:

tell application "iTunes"
    play  -- 播放音乐
    set currentTrack to name of current track  -- 获取当前播放曲目的名称
    display dialog "Now playing: " & currentTrack  -- 显示当前曲目名称
end tell

该脚本会让 iTunes 播放音乐,并显示当前播放的曲目名称。


6. 自动关闭无响应的应用程序

如果某个应用程序没有响应,你可以使用 AppleScript 来强制退出该应用。以下是一个例子,强制退出 Safari:

tell application "System Events"
    set processList to name of every process
    if "Safari" is in processList then
        tell application "Safari" to quit  -- 尝试正常退出
        delay 2  -- 等待2秒
        if "Safari" is in processList then
            tell application "System Events" to keystroke "q" using {command down}  -- 强制退出
        end if
    end if
end tell

这个脚本首先检查 Safari 是否在运行,如果运行则尝试正常退出,如果正常退出失败,则发送 Command + Q​ 快捷键来强制退出 Safari。


进阶技巧与最佳实践

1. 使用 do shell script​ 执行终端命令

AppleScript 可以通过 do shell script​ 执行终端命令,这使得 AppleScript 能够操作系统级别的任务。例如,获取当前的 IP 地址:

set ipAddress to do shell script "ifconfig en0 | grep inet | awk '{print $2}'"
display dialog "Current IP Address: " & ipAddress

该脚本会获取当前 en0​ 网络接口的 IP 地址并显示在对话框中。

2. 定时任务

你可以使用 delay​ 来设置延时执行某个操作,也可以通过创建一个循环来实现定时任务。例如,每10秒钟执行一次某个操作:

repeat
    -- 这里执行你需要定时执行的任务
    display dialog "This is a scheduled task."
    delay 10  -- 每10秒钟执行一次
end repeat

这种方式虽然简单,但是如果你想要更精确的定时任务,建议结合 launchd​ 或 Automator 来完成更高级的定时任务。

3. 与系统偏好设置交互

AppleScript 可以与 macOS 系统偏好设置交互。例如,调整音量、启用或禁用蓝牙等。以下是一个调整音量的示例:

set volume output volume 50  -- 将音量设置为50%

你可以通过 set volume​ 命令来控制系统的音量,范围是 0(静音)到 100(最大音量)。

4. 文件系统操作

AppleScript 在文件系统操作方面非常强大,能够创建、删除、移动文件和文件夹。例如,以下是一个创建新文件夹并移动文件的脚本:

tell application "Finder"
    set folderPath to (path to desktop as text) & "MyFolder"
    make new folder at desktop with properties {name:"MyFolder"}

    -- 移动文件到新文件夹
    set sourceFile to (path to desktop as text) & "example.txt"
    move file sourceFile to folder folderPath
end tell

此脚本首先在桌面创建一个名为 MyFolder​ 的文件夹,然后将名为 example.txt​ 的文件移动到该文件夹中。

5. 异常处理与调试

在编写复杂的脚本时,异常处理和调试至关重要。AppleScript 提供了 try​ 和 on error​ 语句来捕获异常并处理错误。例如:

try
    -- 可能会出错的代码
    set result to (10 / 0)  -- 故意引发除零错误
on error errMsg number errNum
    display dialog "Error: " & errMsg & " (Error code: " & errNum & ")"
end try

这个脚本演示了如何捕获除零错误,并通过对话框显示错误信息。使用 on error​ 块来处理脚本执行中的异常,以避免脚本崩溃。

好的,让我们从更全面、更详细的角度来重新整理并扩展 AppleScript 的进阶技巧与最佳实践。通过增加更多的实际应用案例、深入的技术细节和实用的技巧,我们可以进一步帮助你全面掌握这项强大的自动化工具。


进阶技巧与最佳实践

1. 使用 do shell script​ 执行终端命令

AppleScript 允许你通过 do shell script​ 执行命令行操作,这让它不仅能够与应用程序交互,还能够操作系统底层。利用终端命令,你可以执行如文件操作、网络配置、权限修改等任务。

示例:获取当前网络 IP 地址

通过 ifconfig​ 命令获取网络接口的 IP 地址。你可以用此脚本来监控网络状态或进行其他基于网络的自动化操作。

set ipAddress to do shell script "ifconfig en0 | grep inet | awk '{print $2}'"
display dialog "Current IP Address: " & ipAddress

此脚本通过 ifconfig​ 获取 en0​ 网络接口的 IP 地址,并显示在对话框中。

示例:删除文件并忽略错误

do shell script "rm -f /path/to/file.txt" with administrator privileges

使用 rm -f​ 命令删除文件时,即便文件不存在也不会报错。加上 with administrator privileges​,你可以以管理员身份执行命令,避免权限问题。

示例:批量删除多个文件

假设你需要删除某个文件夹中所有 .log​ 扩展名的文件,可以使用下面的脚本:

do shell script "find /path/to/folder -name '*.log' -exec rm {} \;" with administrator privileges

这个命令会遍历指定文件夹并删除所有 .log​ 文件。通过 find​ 和 rm​ 命令结合,你可以高效地清理文件。


2. 与系统偏好设置交互

AppleScript 提供了对 macOS 系统偏好设置的访问权限,使得你可以自动化很多日常的系统管理任务,如音量控制、显示设置、蓝牙控制等。

示例:调节音量

set volume output volume 50  -- 设置音量为 50%

使用 set volume​ 命令来调节音量,范围是 0 到 100,0 为静音,100 为最大音量。你还可以调整其他音频参数,如输入音量和静音状态。

示例:开启或关闭蓝牙

AppleScript 可以通过 System Preferences​ 应用与蓝牙设置交互,自动开启或关闭蓝牙。

tell application "System Preferences"
    reveal pane id "com.apple.preferences.Bluetooth"  -- 打开蓝牙设置
end tell

这个脚本将会打开蓝牙设置界面,用户可以手动控制蓝牙开关。如果你需要更细粒度的控制(例如启用/禁用蓝牙),则需要结合 do shell script​ 执行相应的 shell 命令。

示例:关闭无线网络

do shell script "networksetup -setairportpower en0 off" with administrator privileges

通过 networksetup​ 命令,你可以关闭系统的无线网络接口 en0​。do shell script​ 结合管理员权限使得这个操作能够顺利进行。


3. 文件系统操作

AppleScript 强大的文件系统操作能力允许你高效地处理文件管理任务,如批量操作文件、重命名文件、移动文件等。你可以通过 Finder​ 应用来进行更直观的文件操作。

示例:创建文件夹并移动文件

tell application "Finder"
    set folderPath to (path to desktop as text) & "MyFolder"
    make new folder at desktop with properties {name:"MyFolder"}
    set sourceFile to (path to desktop as text) & "example.txt"
    move file sourceFile to folder folderPath
end tell

该脚本首先在桌面上创建一个名为 MyFolder​ 的文件夹,然后将桌面上的 example.txt​ 文件移动到该文件夹内。

示例:检查文件夹是否存在

tell application "Finder"
    set folderPath to (path to desktop as text) & "MyFolder"
    if not (exists folder folderPath) then
        make new folder at desktop with properties {name:"MyFolder"}
    end if
end tell

这个脚本会检查桌面上是否已存在 MyFolder​ 文件夹,如果没有,则会创建一个新的文件夹。

示例:批量重命名文件

tell application "Finder"
    set desktopFolder to desktop
    set fileList to files of desktopFolder

    repeat with aFile in fileList
        set fileName to name of aFile
        set newName to "new_" & fileName
        set name of aFile to newName
    end repeat
end tell

这个脚本会遍历桌面上的所有文件,并将它们的文件名前缀改为 new_​。这种批量操作对于处理大量文件时非常有用。

示例:删除指定类型的文件

tell application "Finder"
    set folderPath to (path to desktop as text)
    set fileList to files of folder folderPath
    repeat with aFile in fileList
        if name extension of aFile is "log" then
            delete aFile
        end if
    end repeat
end tell

该脚本会删除桌面上所有扩展名为 .log​ 的文件。这对于定期清理特定类型的日志文件非常方便。


4. 定时任务和事件触发

AppleScript 本身不支持复杂的定时任务调度,但你可以结合 delay​ 语句或者系统级工具(如 launchd​)来实现定时任务和事件触发。

示例:定时执行任务(每 10 秒)

repeat
    -- 执行任务
    display dialog "This is a scheduled task."
    delay 10  -- 每10秒钟执行一次
end repeat

通过使用 delay​,你可以定时执行某个任务。尽管这种方法很简单,但对于需要周期性执行的任务来说非常实用。

示例:使用 launchd​ 创建定时任务

launchd​ 是 macOS 的任务调度工具,可以精确地在指定时间执行 AppleScript 脚本。你可以通过 launchd​ 来设定任务的执行时间、间隔等参数。

下面是一个 .plist​ 配置文件的例子,用于每 10 分钟执行一次 AppleScript 脚本:

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.example.myscript</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/osascript</string>
            <string>/path/to/your/script.scpt</string>
        </array>
        <key>StartInterval</key>
        <integer>600</integer>  <!-- 每10分钟执行一次 -->
        <key>RunAtLoad</key>
        <true/>
    </dict>
</plist>

将该 .plist​ 文件保存到 ~/Library/LaunchAgents/​ 目录下,launchd​ 会自动按照指定的时间间隔执行该脚本。


5. 与外部应用程序集成

AppleScript 可以与许多 macOS 应用程序集成,自动化它们的任务。例如,控制浏览器、邮件客户端、Excel 等常见应用程序。

示例:与 Microsoft Excel 交互

tell application "Microsoft Excel"
    set newWorkbook to make new workbook
    set cellA1 to value of cell "A1" of newWorkbook
    set value of cell "A1" of newWorkbook to "Hello, AppleScript"
end tell

这个脚本会在 Excel 中创建一个新的工作簿,并将 A1​ 单元格的值设置为 "Hello, AppleScript"。

示例:与 Safari 浏览器交互

tell application "Safari"
    open location "http://www.apple.com"  -- 打开指定网站
    activate  -- 激活 Safari 浏览器
end tell

通过这个脚本,AppleScript 可以控制 Safari 打开某个网站,并将浏览器激活到前台。


6.AppleMusic交互

AppleScript 可以与 Apple Music(以前称为 iTunes)进行交互,实现各种自动化操作,如播放控制、获取当前播放歌曲信息、添加歌曲到播放列表等。以下是一些常见的 AppleScript 示例,展示如何与 Apple Music 交互:

  1. 获取当前播放的歌曲信息
tell application "Music"
    if player state is playing then
        set currentTrack to current track
        set trackName to name of currentTrack
        set artistName to artist of currentTrack
        set albumName to album of currentTrack
        display dialog "当前播放的歌曲:" & trackName & " - " & artistName & " - " & albumName
    else
        display dialog "音乐未播放"
    end if
end tell
  1. 播放或暂停音乐
tell application "Music"
    if player state is playing then
        pause
    else
        play
    end if
end tell
  1. 播放下一首歌曲
tell application "Music"
    next track
end tell
  1. 播放上一首歌曲
tell application "Music"
    previous track
end tell
  1. 将当前播放的歌曲添加到播放列表
tell application "Music"
    if player state is playing then
        set currentTrack to current track
        set playlistName to "我的喜欢"
        set targetPlaylist to (first playlist whose name is playlistName)

        if targetPlaylist exists then
            duplicate currentTrack to targetPlaylist
            display dialog "歌曲已添加到播放列表:" & playlistName
        else
            display dialog "播放列表不存在:" & playlistName
        end if
    else
        display dialog "音乐未播放"
    end if
end tell
  1. 创建一个新的播放列表并添加歌曲
tell application "Music"
    if player state is playing then
        set currentTrack to current track
        set playlistName to "新播放列表"

        -- 检查播放列表是否存在
        set playlistExists to false
        repeat with aPlaylist in (get user playlists)
            if (name of aPlaylist) is equal to playlistName then
                set playlistExists to true
                set targetPlaylist to aPlaylist
                exit repeat
            end if
        end repeat

        -- 如果播放列表不存在,则创建新的播放列表
        if not playlistExists then
            set targetPlaylist to make new user playlist with properties {name:playlistName}
        end if

        -- 将当前播放的歌曲添加到播放列表
        duplicate currentTrack to targetPlaylist
        display dialog "歌曲已添加到播放列表:" & playlistName
    else
        display dialog "音乐未播放"
    end if
end tell
  1. 设置音量
tell application "Music"
    set sound volume to 50 -- 设置音量为 50
end tell
  1. 获取当前播放状态
tell application "Music"
    if player state is playing then
        display dialog "音乐正在播放"
    else if player state is paused then
        display dialog "音乐已暂停"
    else
        display dialog "音乐未播放"
    end if
end tell
  1. 操作 AppleMusic 搜索、播放指定音乐
-- 搜索并播放指定歌曲
on searchAndPlayTrack(trackName)
    tell application "Music"
        -- 启动 Music 应用
        launch

        -- 搜索指定歌曲
        set searchResults to (every track of library playlist 1 whose name contains trackName)

        if (count of searchResults) > 0 then
            -- 如果找到歌曲,播放第一首
            set current track to item 1 of searchResults
            play
        else
            -- 如果未找到歌曲,显示提示信息
            display dialog "未找到歌曲:" & trackName
        end if
    end tell
end searchAndPlayTrack

-- 调用函数,搜索并播放指定歌曲
searchAndPlayTrack("Despacito")

运行脚本

你可以将上述脚本保存为一个.scpt​文件,然后使用 AppleScript 编辑器(Script Editor)来运行它,或者在终端中使用osascript​命令来运行:

osascript /path/to/your/script.scpt

配置为服务

如果你经常需要使用这些功能,可以将脚本配置为一个服务,方便在 Finder 中右键菜单中直接调用:

• 打开 Automator(可以在 Launchpad 中找到)。

• 选择“新建文稿”,然后从列表中选择“服务”。

• 在左侧的“操作”面板中,搜索并拖动“运行 AppleScript”到右侧的工作区。

• 将上述 AppleScript 代码粘贴到“运行 AppleScript”操作中。

• 点击“文件”菜单中的“保存”,为服务命名,例如“控制 Apple Music”。

• 打开“系统偏好设置”>“键盘”>“快捷键”>“服务”,找到刚刚创建的服务,为其分配一个快捷键,例如Command + Option + M​。


7. 错误处理与调试

为了确保脚本的稳定运行,错误处理和调试非常重要。通过 try​ 和 on error​ 语句,你可以捕获异常并进行适当处理,避免程序崩溃。

示例:捕获并处理错误

try
    -- 可能会出错的代码
    set result to (10 / 0)  -- 故意引发除零错误
on error errMsg number errNum
    display dialog "Error: " & errMsg & " (" & errNum & ")" 
end try