macOS Ventura下su+grep处理带空格路径的Dock配置问题
macOS Ventura下解决SU+GREP处理带空格Dock路径的转义问题
核心问题分析
原代码的故障根源是多层shell执行时的字符串解析冲突:手动转义的空格或单引号包裹的路径,在su -c的子shell中会被二次解析,导致路径被拆分成多个参数,最终grep无法匹配完整路径,进而重复添加Dock图标。
解决方案:用BASH -S传递参数避免转义
通过su - user -c 'bash -s' -- "$param"的方式,将带空格的路径作为参数直接传递给子shell,完全绕开手动转义的坑。同时优化Dock项检查逻辑,确保匹配精准。
修改后的完整代码
__dock_item() { printf '%s%s%s%s%s' \ '<dict><key>tile-data</key><dict><key>file-data</key><dict>' \ '<key>_CFURLString</key><string>' \ "$1" \ '</string><key>_CFURLStringType</key><integer>0</integer>' \ '</dict></dict></dict>' } # 获取当前登录用户(MDM脚本必备) current_user=$(stat -f "%Su" /dev/console) for dockItem in /Applications/Google\ Chrome.app /Applications/Slack.app /Applications/zoom.us.app "Done"; do echo "$dockItem" if [[ -e "$dockItem" ]]; then if [[ "$dockItem" != "Done" ]]; then # 用bash -s传递参数,避免转义错误 if /usr/bin/su - "$current_user" -c 'bash -s' -- "$dockItem" <<'EOF' dock_path="$1" defaults read com.apple.dock persistent-apps | grep -q "$dock_path" EOF then printf '%s\n' 'Dock图标已存在。' else printf '%s\n' '正在添加Dock图标...' # 同样用参数传递方式生成并添加Dock项 /usr/bin/su - "$current_user" -c 'bash -s' -- "$dockItem" <<'EOF' dock_path="$1" dock_item=$(printf '%s%s%s%s%s' \ '<dict><key>tile-data</key><dict><key>file-data</key><dict>' \ '<key>_CFURLString</key><string>' \ "$dock_path" \ '</string><key>_CFURLStringType</key><integer>0</integer>' \ '</dict></dict></dict>') defaults write com.apple.dock persistent-apps -array-add "$dock_item" EOF fi fi else printf '%s\n' '重启Dock...' killall Dock fi done
关键改进点
- 参数传递方式:
su - "$current_user" -c 'bash -s' -- "$dockItem"通过bash -s让子shell从标准输入读取命令,--后的参数会被完整传递给子shell的$1,彻底避免空格拆分问题。 - 单引号HEREDOC:
<<'EOF'确保 heredoc 内的变量不会被当前shell解析,仅在子shell中生效,保证参数传递的准确性。 - 精准用户获取:添加
current_user=$(stat -f "%Su" /dev/console)确保获取当前登录的交互用户,MDM脚本中必须明确这一点。
进阶优化:用PLUTIL+JQ精准匹配
如果允许使用jq工具(可通过MDM预装),可以替换grep检查逻辑,避免部分字符串匹配的误判:
# 替换原有检查代码 if /usr/bin/su - "$current_user" -c 'bash -s' -- "$dockItem" <<'EOF' dock_path="$1" defaults read com.apple.dock persistent-apps | plutil -convert json -o - - | jq -e '.[] | ."tile-data"."file-data"."_CFURLString" == "'"$dock_path"'"' >/dev/null EOF
内容的提问来源于stack exchange,提问作者FridaeCoffee
相关产品推荐
相关产品推荐

