macos 26.2 将微信安装到移动硬盘
一、前言之前参考https://blog.csdn.net/qq_39921135/article/details/146149096文章把微信迁移到了外接磁盘内置硬盘秒变小很多看到磁盘变小了手贱从 macOS 14.4.1 - macOS 26.2 ,中间两年没更新系统了更新完26.2就后悔了是真的丑好在微信还能正常使用。过了一段时间微信突然不能启动了按照文章跑了一遍跑成功过一次后又出问题了之后就没用mac上的微信了。mac上没有方便是真的不方便然后就想着解决二、下载软件2.1 创建/Volumes/OWC/Applications文件夹2.2 双击dmg包会出现如图(图片借用)不要将软件拖到右侧的application里面将软件直接拖到外置盘的文件夹里/Volumes/OWC/Applications。2.3 在 /Applications 建符号链接让 Launchpad 和 Spotlight 找得到cd /Applications ln -s /Volumes/OWC/Applications/WeChat.app⚠️ 必须先 cd /Applications否则容易把符号链接误建到 App 包内部导致签名失效微信会报已损坏。2.4 清掉 quarantineChrome 下载后系统加的隔离标记xattr -dr com.apple.quarantine /Volumes/OWC/Applications/WeChat.app到这一步软件能启动了但聊天记录还会写到内置盘。下面才是关键。三、方案架构外置硬盘上原来只有一个卷比如叫OWC我们在同一个 APFS Container 里再切一个独立卷WeChatFiles。两个卷物理上都在外置硬盘的同一个 SSD 上共享空间池外置硬盘物理 SSDAPFS Container disk51.7 TB 共享池 ├── 卷 OWCdisk5s1 ← 你日常使用的, 挂在 /Volumes/OWC └── 卷 WeChatFilesdisk5s2 ← 新建的, 挂在家目录路径下, Finder 看不到WeChatFiles卷的挂载点直接指向家目录路径/dev/disk5s2 → /Users/user/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/家目录前缀/Users/...是 sandbox 允许微信访问的/Volumes/...不允许。子目录挂载点不会触发 root data flag 校验。一切就跑通了。最后用 LaunchAgent 配置开机自动挂载OK。四、一键安装脚本4.1 退出微信备份数据~/Library/Containers/com.tencent.xinWeChat把这个文件夹备份到你的移动磁盘上注意文件大小要一样或者通过命令备份ditto ~/Library/Containers/com.tencent.xinWeChat \/Volumes/你的外接磁盘/wechat_backup_$(date %Y%m%d)4.2 创建脚本touch wechat_to_external.shchmod x wechat_to_external.sh4.3 脚本内容#!/usr/bin/env bash # 微信迁移到外接硬盘 - 一键脚本 (macOS 26 适用) # # 适用场景: 当前微信在内置盘默认路径, 想把聊天记录和附件搬到外接盘 # 兼容: macOS 26.x / Apple Silicon # # 前提: # 1. 外接盘格式必须是 APFS, 卷名默认 OWC (可改 EXT_VOLUME 环境变量) # 2. WeChat.app 已经放到 /Volumes/OWC/Applications/ (按文章第二部分操作) # # 用法: # chmod x wechat_to_external.sh # ./wechat_to_external.sh # 默认外接盘卷名 OWC # EXT_VOLUMEMyDisk ./wechat_to_external.sh # 自定义卷名 # # 脚本可重复执行, 已完成的步骤会自动跳过. set -u # 可配置 EXT_VOLUME${EXT_VOLUME:-OWC} DATA_VOLUME_NAMEWeChatFiles LAUNCHAGENT_LABELcom.user.wechat-userdata-mount # EXT_MOUNT/Volumes/$EXT_VOLUME APP_PATH$EXT_MOUNT/Applications/WeChat.app CONTAINER$HOME/Library/Containers/com.tencent.xinWeChat USERDATA_DIR$CONTAINER/Data/Documents/xwechat_files LAUNCHAGENT_PLIST$HOME/Library/LaunchAgents/$LAUNCHAGENT_LABEL.plist red() { printf \033[31m%s\033[0m\n $*; } green() { printf \033[32m%s\033[0m\n $*; } yellow(){ printf \033[33m%s\033[0m\n $*; } step() { printf \n\033[1;36m[%s]\033[0m %s\n $1 $2; } die() { red ❌ $*; exit 1; } # ---- 0. 前置检查 ---- step 0/7 前置检查 [ -d $EXT_MOUNT ] || die 外接盘 $EXT_MOUNT 未挂载 [ -d $APP_PATH ] || die $APP_PATH 不存在 (按文章第二部分先把 WeChat.app 拖进去) EXT_FS$(diskutil info $EXT_MOUNT | awk -F: * /File System Personality/{print $2} | xargs) [ $EXT_FS APFS ] || die 外接盘不是 APFS (当前 $EXT_FS), 请在磁盘工具抹掉为 APFS EXT_DISK$(diskutil info $EXT_MOUNT | awk -F: * /Part of Whole/{print $2} | xargs) [ -n $EXT_DISK ] || die 无法定位 $EXT_MOUNT 所在容器 green 外接盘: $EXT_MOUNT (APFS, 容器 $EXT_DISK) green 微信 App: $APP_PATH # 退出微信 if pgrep -lf WeChat.app/Contents/MacOS/WeChat /dev/null; then yellow 微信正在运行, 退出... osascript -e tell application WeChat to quit 2/dev/null || true sleep 3 pkill -9 -f WeChat.app/Contents/MacOS/WeChat 2/dev/null || true pkill -9 -f WeChatAppEx 2/dev/null || true sleep 2 pgrep -lf WeChat.app/Contents/MacOS/WeChat /dev/null die 微信无法退出, 请手动 CmdQ fi # ---- 1. 让微信容器存在(若不存在则启动一次让 macOS 创建) ---- step 1/7 确保微信容器存在 (内置盘) if [ ! -d $CONTAINER ]; then yellow 容器不存在, 启动微信一次让 macOS 创建... open -a $APP_PATH for i in 1 2 3 4 5 6 7 8 9 10; do sleep 1 [ -d $CONTAINER ] break done [ -d $CONTAINER ] || die 微信启动失败, 容器未创建 osascript -e tell application WeChat to quit 2/dev/null || true sleep 3 pkill -9 -f WeChat.app/Contents/MacOS/WeChat 2/dev/null || true sleep 2 fi green 容器: $CONTAINER # ---- 2. 备份当前 xwechat_files (内置盘上的聊天记录, 准备迁移) ---- step 2/7 备份当前内置盘上的聊天记录 # 检查挂载点是否已经被外接卷占用 (重复执行场景) EXISTING$(mount | awk -v p$USERDATA_DIR $0 ~ on p {print $1}) RESUME_MODE0 if [ -n $EXISTING ]; then EXIST_VOL$(diskutil info $EXISTING 2/dev/null | awk -F: * /Volume Name/{print $2} | xargs) if [ $EXIST_VOL $DATA_VOLUME_NAME ]; then yellow 检测到 $DATA_VOLUME_NAME 卷已挂载 (上次未跑完?), 进入续传模式 yellow 已复制大小: $(du -sh $USERDATA_DIR 2/dev/null | cut -f1) RESUME_MODE1 else die 挂载点被未知卷 $EXISTING 占用, 手动卸载: diskutil unmount $USERDATA_DIR fi fi if [ $RESUME_MODE -eq 0 ]; then if [ -d $USERDATA_DIR ] [ $(ls -A $USERDATA_DIR 2/dev/null) ]; then BACKUP_TMP$HOME/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files.bak_$(date %Y%m%d_%H%M%S) SIZE$(du -sh $USERDATA_DIR 2/dev/null | cut -f1) yellow 当前内置盘聊天记录大小: $SIZE yellow 暂时改名为: $BACKUP_TMP mv $USERDATA_DIR $BACKUP_TMP BACKUP_SOURCE$BACKUP_TMP green ✓ 备份完成 else yellow 当前 xwechat_files 是空的 (微信未登录过) BACKUP_SOURCE fi mkdir -p $USERDATA_DIR fi # ---- 3. 在外接盘新切 WeChatFiles 子卷 ---- if [ $RESUME_MODE -eq 1 ]; then step 3/7 续传模式 - 跳过创建卷 DATA_DEV${EXISTING#/dev/} else step 3/7 在外接盘 $EXT_DISK 新切 $DATA_VOLUME_NAME 子卷 DATA_DEV$(diskutil apfs list $EXT_DISK 2/dev/null \ | awk -v name$DATA_VOLUME_NAME /Volume disk/{dev$3} $0 ~ Name:[[:space:]]name[[:space:]]{print dev; exit}) if [ -n $DATA_DEV ]; then yellow $DATA_VOLUME_NAME 卷已存在: $DATA_DEV (复用) else yellow 创建新卷 (会请求一次管理员密码)... osascript -e do shell script \diskutil apfs addVolume $EXT_DISK APFS $DATA_VOLUME_NAME -nomount\ with administrator privileges 21 | tail -2 sleep 1 DATA_DEV$(diskutil apfs list $EXT_DISK \ | awk -v name$DATA_VOLUME_NAME /Volume disk/{dev$3} $0 ~ Name:[[:space:]]name[[:space:]]{print dev; exit}) [ -n $DATA_DEV ] || die 创建卷失败 green 新卷: $DATA_DEV fi fi DATA_UUID$(diskutil info $DATA_DEV | awk -F: * /Volume UUID/{print $2} | xargs) [ -n $DATA_UUID ] || die 无法获取卷 UUID # ---- 4. 挂载到 xwechat_files 子目录 ---- if [ $RESUME_MODE -eq 1 ]; then step 4/7 续传模式 - 跳过挂载 else step 4/7 挂载子卷到 $USERDATA_DIR osascript APPLESCRIPT do shell script diskutil mount -mountPoint $USERDATA_DIR $DATA_DEV 21 | tail -1 diskutil enableOwnership $USERDATA_DIR 21 | tail -1 chown $USER:staff $USERDATA_DIR chmod 700 $USERDATA_DIR with administrator privileges APPLESCRIPT mount | grep -q on $USERDATA_DIR || die 挂载失败 green 挂载成功, 物理盘: $(df $USERDATA_DIR | tail -1 | awk {print $1}) fi # ---- 5. 把内置盘备份的聊天记录复制到新挂载点 ---- step 5/7 把聊天记录从内置盘复制到外接盘 # 续传模式下源是之前留下的 .bak_ 目录 if [ $RESUME_MODE -eq 1 ]; then BACKUP_SOURCE$(ls -dt $HOME/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files.bak_* 2/dev/null | head -1) fi if [ -n ${BACKUP_SOURCE:-} ] [ -d $BACKUP_SOURCE ]; then SRC_SIZE$(du -sh $BACKUP_SOURCE 2/dev/null | cut -f1) DST_SIZE$(du -sh $USERDATA_DIR 2/dev/null | cut -f1) echo 源: $BACKUP_SOURCE ($SRC_SIZE) echo 目标: $USERDATA_DIR (当前 $DST_SIZE) echo ditto 期间无输出, 每 60 秒打一次进度... (while sleep 60; do echo [$(date %H:%M:%S)] 已复制 $(du -sh $USERDATA_DIR 2/dev/null | cut -f1) done) PROGRESS_PID$! START_TS$(date %s) ditto $BACKUP_SOURCE $USERDATA_DIR DITTO_EXIT$? ELAPSED$(( $(date %s) - START_TS )) kill $PROGRESS_PID 2/dev/null wait $PROGRESS_PID 2/dev/null if [ $DITTO_EXIT -ne 0 ]; then red ditto 失败 (退出码 $DITTO_EXIT), 备份保留在: $BACKUP_SOURCE exit 1 fi green ✓ 复制完成, 耗时 $((ELAPSED/60))分$((ELAPSED%60))秒 green 内置盘备份保留: $BACKUP_SOURCE (确认微信能正常用之后, 可手动删除回收空间) else yellow 无内置盘聊天记录需要迁移, 跳过 fi # ---- 6. 安装 LaunchAgent (开机自动挂载) ---- step 6/7 安装 LaunchAgent (开机自动挂载子卷) mkdir -p $HOME/Library/LaunchAgents cat $LAUNCHAGENT_PLIST EOF ?xml version1.0 encodingUTF-8? !DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd plist version1.0 dict keyLabel/key string$LAUNCHAGENT_LABEL/string keyProgramArguments/key array string/bin/bash/string string-c/string stringfor i in 1 2 3 4 5 6 7 8 9 10; do if /usr/sbin/diskutil info $DATA_UUID /dev/null 2amp;1; then /usr/sbin/diskutil mount -mountPoint $USERDATA_DIR $DATA_UUID amp;amp; exit 0; fi; sleep 3; done; exit 1/string /array keyRunAtLoad/key true/ keyStandardOutPath/key string/tmp/$LAUNCHAGENT_LABEL.out/string keyStandardErrorPath/key string/tmp/$LAUNCHAGENT_LABEL.err/string /dict /plist EOF launchctl bootout gui/$(id -u)/$LAUNCHAGENT_LABEL 2/dev/null || true launchctl bootstrap gui/$(id -u) $LAUNCHAGENT_PLIST \ || die LaunchAgent 加载失败 green ✓ LaunchAgent 已安装 # ---- 7. 启动微信 ---- step 7/7 启动微信 open -a $APP_PATH sleep 7 if pgrep -lf WeChat.app/Contents/MacOS/WeChat /dev/null; then green ✅ 微信已启动 else red ❌ 微信启动失败, 看日志: log show --last 30s --predicate process WeChat OR process containermanagerd --style compact 21 | tail -20 exit 1 fi # ---- 摘要 ---- cat EOF ✅ 全部完成! 微信 App: $APP_PATH (外接盘) 容器壳: $CONTAINER (内置盘, ~100KB sandbox 元数据) 聊天数据: $USERDATA_DIR 物理: $(df $USERDATA_DIR | tail -1 | awk {print $1}) (外接盘) 内置盘备份(临时): $HOME/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files.bak_* 验证微信正常工作后, 可手动 rm -rf 回收空间 验证数据真在外接盘: df -h $USERDATA_DIR 应显示 /dev/disk?s2 (而不是 /dev/disk3sX) EOF