前言:Automator与Shell脚本的协同力量

在黑苹果的日常使用中,系统维护、批量操作和重复性任务占据了大量时间。macOS自带的Automator工具提供了图形化的工作流编排能力,而Shell脚本则提供了精确的程序化控制。当两者结合使用时,能够构建出强大的自动化系统——从批量重命名文件到定期清理系统缓存,从一键配置开发环境到自动备份重要数据。本文将从Automator的基础操作到Shell脚本的高级技巧,全面讲解黑苹果环境下的深度自动化实战。

一、Automator工作流基础

1.1 Automator的工作流类型

Automator提供以下工作流类型:

  • 工作流(Workflow):在Automator内运行的通用工作流
  • 应用程序(Application):可独立运行的应用程序,接受拖放输入
  • 快速操作(Quick Action):集成到右键菜单和Finder的工具栏
  • 打印插件(Print Plugin):在打印对话框中可用
  • 文件夹操作(Folder Action):当文件添加到指定文件夹时自动触发
  • 日历提醒(Calendar Alarm):在日历事件触发时运行
  • 图像捕获插件(Image Capture Plugin):在图像捕获应用中可用

对于黑苹果用户,最常用的是快速操作(右键菜单集成)和文件夹操作(自动处理新文件)。

1.2 创建第一个快速操作

以下是一个实用的快速操作——将选中的图片批量转换为WebP格式:

  1. 打开Automator → 新建 → 快速操作
  2. 设置"工作流程收到当前"为"图像文件",位于"Finder.app"
  3. 从左侧库中拖入"运行Shell脚本"动作
  4. 设置Shell为/bin/bash,传递输入为"作为自变量"
  5. 输入以下脚本:
#!/bin/bash
# 批量转换图片为WebP格式
# 需要先安装webp工具:brew install webp

for f in "$@"; do
    # 获取文件扩展名和目录
    dir="$(dirname "$f")"
    base="$(basename "$f" | sed 's/\.[^.]*$//')"
    
    # 转换为WebP,质量85%
    cwebp -q 85 "$f" -o "${dir}/${base}.webp" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        echo "转换成功: ${base}.webp"
    else
        echo "转换失败: $f"
    fi
done

# 发送通知
osascript -e "display notification \"WebP转换完成\" with title \"Automator\""

保存为"转换为WebP"后,在Finder中右键点击图片文件即可看到该选项。

二、文件夹操作自动化

2.1 自动整理下载文件夹

创建一个文件夹操作,当新文件添加到Downloads文件夹时,自动按文件类型整理到子目录:

#!/bin/bash
# auto_organize_downloads.sh
# 附加到 ~/Downloads 文件夹的文件夹操作

DOWNLOADS="$HOME/Downloads"

# 定义文件类型分类
declare -A CATEGORIES
CATEGORIES["文档"]="pdf doc docx xls xlsx ppt pptx txt rtf odt"
CATEGORIES["图片"]="jpg jpeg png gif bmp svg webp ico tiff psd"
CATEGORIES["视频"]="mp4 mkv avi mov wmv flv webm m4v"
CATEGORIES["音频"]="mp3 wav flac aac ogg wma m4a"
CATEGORIES["压缩包"]="zip rar 7z tar gz bz2 xz dmg"
CATEGORIES["代码"]="py js ts html css json xml yaml yml sh bat"
CATEGORIES["安装包"]="pkg dmg app"

# 处理添加的文件
for f in "$@"; do
    # 跳过目录和隐藏文件
    [ -d "$f" ] && continue
    basename "$(basename "$f")" | grep -q "^\." && continue
    
    # 获取文件扩展名
    ext="${f##*.}"
    ext=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
    
    # 查找匹配的分类
    target_dir=""
    for category in "${!CATEGORIES[@]}"; do
        if echo "${CATEGORIES[$category]}" | grep -qw "$ext"; then
            target_dir="$DOWNLOADS/$category"
            break
        fi
    done
    
    # 如果没有匹配的分类,放入"其他"
    [ -z "$target_dir" ] && target_dir="$DOWNLOADS/其他"
    
    # 创建目标目录并移动文件
    mkdir -p "$target_dir"
    mv "$f" "$target_dir/"
    echo "移动: $(basename "$f") → $target_dir/"
done

2.2 自动转换HEIC照片

黑苹果用户经常从iPhone接收HEIC格式照片,在部分应用中不兼容。创建自动转换的文件夹操作:

#!/bin/bash
# auto_convert_heic.sh
# 监控指定文件夹,自动将HEIC转换为JPEG

WATCH_DIR="$HOME/Pictures/HEIC_Inbox"
OUTPUT_DIR="$HOME/Pictures/JPEG_Output"

mkdir -p "$OUTPUT_DIR"

for f in "$@"; do
    ext="${f##*.}"
    if [ "$(echo "$ext" | tr '[:upper:]' '[:lower:]')" = "heic" ]; then
        base="$(basename "$f" | sed 's/\.[^.]*$//')"
        
        # 使用sips(macOS内置图片处理工具)转换
        sips -s format jpeg -s formatOptions 95 "$f" --out "${OUTPUT_DIR}/${base}.jpg"
        
        if [ $? -eq 0 ]; then
            echo "转换成功: ${base}.jpg"
            # 可选:转换成功后删除原文件
            # rm "$f"
        fi
    fi
done

使用macOS内置的sips工具而非ImageMagick,无需额外安装依赖。

三、Shell脚本高级自动化

3.1 黑苹果系统维护脚本

以下是一键式的黑苹果系统维护脚本,涵盖常见维护任务:

#!/bin/bash
# hackintosh_maintenance.sh
# 黑苹果一键系统维护脚本

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log_info()  { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn()  { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# 1. 清理系统缓存
clean_caches() {
    log_info "清理系统缓存..."
    
    # 清理用户缓存
    du -sh ~/Library/Caches/ 2>/dev/null || true
    find ~/Library/Caches/ -type f -mtime +30 -delete 2>/dev/null || true
    log_info "已清理30天以上的用户缓存文件"
    
    # 清理Xcode派生数据
    if [ -d ~/Library/Developer/Xcode/DerivedData ]; then
        du -sh ~/Library/Developer/Xcode/DerivedData/
        rm -rf ~/Library/Developer/Xcode/DerivedData/*
        log_info "已清理Xcode DerivedData"
    fi
    
    # 清理Homebrew缓存
    if command -v brew &>/dev/null; then
        brew cleanup --prune=30 -s 2>/dev/null || true
        log_info "已清理Homebrew缓存"
    fi
}

# 2. 修复磁盘权限
repair_permissions() {
    log_info "验证启动盘..."
    
    # 验证APFS卷宗
    diskutil verifyVolume / 2>/dev/null || true
    
    # 修复用户目录权限
    diskutil resetUserPermissions / $(id -u) 2>/dev/null || true
    log_info "已重置用户权限"
}

# 3. 清理系统日志
clean_logs() {
    log_info "清理系统日志..."
    
    # 删除30天前的系统日志
    sudo find /private/var/log/ -type f -mtime +30 -delete 2>/dev/null || true
    
    # 清理诊断报告
    find ~/Library/Logs/DiagnosticReports/ -type f -mtime +30 -delete 2>/dev/null || true
    find /Library/Logs/DiagnosticReports/ -type f -mtime +30 -delete 2>/dev/null || true
    
    # 清理统一日志
    sudo log erase --ttl 7 2>/dev/null || true
    log_info "已清理过期日志"
}

# 4. 检查EFI分区
check_efi() {
    log_info "检查EFI分区..."
    
    # 查找EFI分区
    EFI_PARTITION=$(diskutil list | grep EFI | head -1 | awk '{print $NF}')
    if [ -n "$EFI_PARTITION" ]; then
        log_info "EFI分区: /dev/$EFI_PARTITION"
        
        # 检查EFI分区使用率
        sudo diskutil mount $EFI_PARTITION 2>/dev/null || true
        df -h /Volumes/EFI 2>/dev/null || true
    else
        log_warn "未找到EFI分区"
    fi
}

# 5. 系统健康报告
health_report() {
    log_info "====== 系统健康报告 ======"
    
    # 内存使用
    memory_pressure | head -3
    
    # 磁盘使用
    df -h / | tail -1
    
    # S.M.A.R.T状态(如果安装了smartmontools)
    if command -v smartctl &>/dev/null; then
        DISK=$(diskutil info / | grep "Device Node" | awk '{print $NF}')
        smartctl -H "$DISK" 2>/dev/null || true
    fi
    
    # 运行时间
    uptime
    
    # 最近Kernel Panic
    RECENT_PANICS=$(ls -lt /Library/Logs/DiagnosticReports/*panic* 2>/dev/null | head -3)
    if [ -n "$RECENT_PANICS" ]; then
        log_warn "发现最近的Kernel Panic报告:"
        echo "$RECENT_PANICS"
    else
        log_info "无最近Kernel Panic"
    fi
}

# 执行所有维护任务
echo "========================================="
echo "  黑苹果系统维护脚本"
echo "  $(date)"
echo "========================================="

health_report
clean_caches
clean_logs
repair_permissions
check_efi

echo ""
log_info "维护完成!"

3.2 OpenCore EFI自动备份脚本

#!/bin/bash
# oc_efi_backup.sh
# 自动备份OpenCore EFI分区

BACKUP_ROOT="$HOME/OC_Backups"
TIMESTAMP=$(date "+%Y%m%d_%H%M%S")
BACKUP_DIR="${BACKUP_ROOT}/EFI_${TIMESTAMP}"

# 创建备份目录
mkdir -p "$BACKUP_DIR"

# 查找并挂载EFI分区
EFI_DISK=$(diskutil list | grep EFI | head -1 | awk '{print $NF}')

if [ -z "$EFI_DISK" ]; then
    echo "错误:未找到EFI分区"
    exit 1
fi

echo "挂载EFI分区: /dev/$EFI_DISK"
sudo diskutil mount /dev/$EFI_DISK

# 复制EFI内容
EFI_PATH="/Volumes/EFI"
if [ -d "$EFI_PATH/EFI" ]; then
    cp -R "$EFI_PATH/EFI" "$BACKUP_DIR/"
    echo "备份完成: $BACKUP_DIR"
    
    # 记录当前SMBIOS信息
    ioreg -l | grep -i "serial-number" > "$BACKUP_DIR/smbios_info.txt" 2>/dev/null || true
    
    # 记录config.plist哈希
    shasum -a 256 "$BACKUP_DIR/EFI/OC/config.plist" > "$BACKUP_DIR/config_hash.txt"
else
    echo "错误:EFI分区内容不存在"
fi

# 卸载EFI分区
sudo diskutil unmount /dev/$EFI_DISK

# 保留最近10个备份
cd "$BACKUP_ROOT"
ls -t | tail -n +11 | xargs rm -rf 2>/dev/null || true

echo "自动清理完成,保留最近10个备份"

3.3 开发环境一键部署脚本

#!/bin/bash
# dev_setup.sh
# 黑苹果开发环境一键部署

set -e

echo "====== 黑苹果开发环境部署 ======"

# 1. 安装Xcode命令行工具
if ! xcode-select -p &>/dev/null; then
    echo "安装Xcode命令行工具..."
    xcode-select --install
    echo "请等待Xcode命令行工具安装完成后重新运行此脚本"
    exit 0
fi

# 2. 安装Homebrew
if ! command -v brew &>/dev/null; then
    echo "安装Homebrew..."
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi

# 3. 安装基础开发工具
echo "安装基础开发工具..."
brew install --formula \
    git curl wget tree jq htop tmux \
    python@3.12 node@22 go rust \
    neovim ripgrep fd bat eza \
    ffmpeg imagemagick

# 4. 安装常用应用
echo "安装常用应用..."
brew install --cask \
    visual-studio-code iterm2 \
    docker desktop slack discord

# 5. 配置Git
if [ ! -f ~/.gitconfig ]; then
    echo "配置Git..."
    read -p "Git用户名: " git_name
    read -p "Git邮箱: " git_email
    git config --global user.name "$git_name"
    git config --global user.email "$git_email"
    git config --global init.defaultBranch main
    git config --global core.editor nvim
fi

# 6. 配置Shell
if [ ! -d ~/.oh-my-zsh ]; then
    echo "安装Oh My Zsh..."
    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
fi

# 7. 配置Python虚拟环境
pip3 install --user virtualenv poetry black isort mypy ruff

# 8. 配置Node.js
npm install -g typescript ts-node pnpm

echo ""
echo "====== 部署完成 ======"
echo "请重启终端以使所有配置生效"

四、Automator与Shell脚本深度集成

4.1 通过Automator创建右键菜单脚本

将Shell脚本封装为快速操作,添加到Finder右键菜单:

  1. 打开Automator → 新建"快速操作"
  2. 设置接收类型为"文件或文件夹",位于"Finder"
  3. 添加"运行Shell脚本"动作
  4. 编写处理逻辑

实用的快速操作示例——计算文件夹大小:

#!/bin/bash
# 在Finder右键菜单中显示选中文件夹的总大小

for f in "$@"; do
    if [ -d "$f" ]; then
        size=$(du -sh "$f" 2>/dev/null | awk '{print $1}')
        osascript -e "display notification \"$(basename "$f"): $size\" with title \"文件夹大小\""
    fi
done

4.2 通过launchd定时执行Shell脚本

将维护脚本配置为定时任务:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.yoozai.hackintosh-maintenance</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/hackintosh_maintenance.sh</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>3</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/tmp/hackintosh_maintenance.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/hackintosh_maintenance_err.log</string>
</dict>
</plist>
# 安装launchd定时任务
cp com.yoozai.hackintosh-maintenance.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.yoozai.hackintosh-maintenance.plist

# 验证任务是否加载
launchctl list | grep yoozai

4.3 使用osascript实现跨应用自动化

osascript允许Shell脚本控制macOS应用程序,实现跨应用自动化:

#!/bin/bash
# morning_routine.sh
# 早晨工作准备自动化脚本

# 1. 调整显示器亮度到70%
osascript -e 'tell application "System Events" to key code 107' # 降低亮度
# 或使用brightnessctl(需要安装)

# 2. 打开常用应用
open -a "Safari"
open -a "Mail"
open -a "Slack"
open -a "Visual Studio Code"

# 3. 在Safari中打开常用标签页
osascript -e '
tell application "Safari"
    activate
    open location "https://github.com"
    delay 1
    tell application "System Events" to keystroke "t" using command down
    open location "https://stackoverflow.com"
end tell'

# 4. 设置勿扰模式(macOS 12+)
osascript -e '
tell application "System Events"
    tell process "ControlCenter"
        -- 点击控制中心的勿扰模式按钮
    end tell
end tell'

# 5. 播放欢迎提示音
afplay /System/Library/Sounds/Glass.aiff

# 6. 显示通知
osascript -e 'display notification "工作环境已准备就绪" with title "早晨准备" sound name "Glass"'

五、黑苹果特有的自动化场景

5.1 自动检测kext更新

#!/bin/bash
# check_kext_updates.sh
# 检查OpenCore kext是否有新版本

EFI_PATH="/Volumes/EFI/EFI/OC"
KEXT_DIR="$EFI_PATH/Kexts"

# 挂载EFI
sudo diskutil mount $(diskutil list | grep EFI | head -1 | awk '{print $NF}')

echo "====== Kext版本检查 ======"

# 检查Lilu
if [ -f "$KEXT_DIR/Lilu.kext/Contents/Info.plist" ]; then
    local_version=$(plutil -extract CFBundleVersion xml1 -o - "$KEXT_DIR/Lilu.kext/Contents/Info.plist" | grep string | awk -F'[><]' '{print $3}')
    echo "Lilu: 本地版本 $local_version"
fi

# 检查WhateverGreen
if [ -f "$KEXT_DIR/WhateverGreen.kext/Contents/Info.plist" ]; then
    local_version=$(plutil -extract CFBundleVersion xml1 -o - "$KEXT_DIR/WhateverGreen.kext/Contents/Info.plist" | grep string | awk -F'[><]' '{print $3}')
    echo "WhateverGreen: 本地版本 $local_version"
fi

# 检查AppleALC
if [ -f "$KEXT_DIR/AppleALC.kext/Contents/Info.plist" ]; then
    local_version=$(plutil -extract CFBundleVersion xml1 -o - "$KEXT_DIR/AppleALC.kext/Contents/Info.plist" | grep string | awk -F'[><]' '{print $3}')
    echo "AppleALC: 本地版本 $local_version"
fi

# 使用GitHub API检查最新版本
echo ""
echo "====== GitHub最新版本 ======"
for repo in "acidanthera/Lilu" "acidanthera/WhateverGreen" "acidanthera/AppleALC"; do
    latest=$(curl -s "https://api.github.com/repos/$repo/releases/latest" | grep '"tag_name"' | sed 's/.*"tag_name": "\([^"]*\)".*/\1/')
    echo "$repo: $latest"
done

5.2 自动同步EFI配置到云存储

#!/bin/bash
# sync_efi_cloud.sh
# 将EFI配置自动同步到本地Git仓库

EFI_BACKUP_REPO="$HOME/EFI-Config"
EFI_PATH="/Volumes/EFI"

# 挂载EFI
sudo diskutil mount $(diskutil list | grep EFI | head -1 | awk '{print $NF}')

# 同步文件
rsync -av --delete \
    --exclude='.Trashes' \
    --exclude='.fseventsd' \
    "$EFI_PATH/EFI/" "$EFI_BACKUP_REPO/EFI/"

# 提交到Git
cd "$EFI_BACKUP_REPO"
git add -A
if git diff --cached --quiet; then
    echo "无变更需要提交"
else
    git commit -m "EFI配置更新 $(date '+%Y-%m-%d %H:%M')"
    git push
    echo "EFI配置已同步到远程仓库"
fi

六、安全注意事项

6.1 Shell脚本安全最佳实践

  • 始终使用set -e在错误时退出
  • 使用set -u检测未定义变量
  • 使用set -o pipefail检测管道中的错误
  • 对用户输入进行验证和转义
  • 避免使用sudo除非必要,必要时提示用户输入密码
  • 在删除操作前进行确认

6.2 Automator工作流安全

  • 首次运行时系统会请求辅助功能权限,需要手动授权
  • 包含Shell脚本的工作流无法通过代码签名,需要用户手动允许
  • 分发工作流时建议附带源码说明,便于安全审计

七、总结

Automator和Shell脚本的结合为黑苹果用户提供了强大的自动化能力。从简单的文件处理到复杂的系统维护,从图形化的工作流录制到精确的命令行控制,这两种工具互为补充,覆盖了几乎所有的自动化需求。核心建议:

  1. 从简单开始:先创建简单的快速操作,逐步构建复杂工作流
  2. 善用文件夹操作:实现真正的"无感自动化"
  3. 脚本版本管理:将所有Shell脚本纳入Git管理
  4. 安全优先:所有脚本遵循安全编码规范
  5. 定期审查:定期检查launchd定时任务和自动化脚本的有效性

自动化是效率的倍增器。当你把重复性任务交给机器处理,就能将精力集中在真正有创造性的工作上——这才是黑苹果用户追求的终极目标。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。