Bash脚本-如何使用函数来确定我的变量将使用文件1还是文件2



我要做的是(在Mac OS X/MacOS中(使用osascript在中创建一个对话框。我想给它添加一个图标。这个部分很简单,也很有效。

然而,问题是,如果用户处于黑暗或明亮模式,我的图标文件将不会看起来正确。因此,我有两个.icns文件,它们存储在我的环境中的所有Mac电脑上的一个特定目录中(该目录位于/Library/ctxsit/(。我可以使用变量调用其中一个,但当我添加一个函数来确定要使用哪个文件时,它会失败。

首先,起作用的部分是:

icon=(/Library/ctxsit/CompanyIconB.icns)
title="Company IT Notification"
echo $title
prompt=$(osascript -e "display dialog "Click Continue to logout from current user and set this Mac back to the Welcome Screen. This will leave the current user directory and profile intact.
Please make sure your work is saved. After Continuing, the device will appear to be in a Fresh OS state.  
        " buttons {"Cancel", "Continue"} with title "$title" default button 2 with icon "$icon" ")
if [[ $prompt == "button returned:Continue" ]] 
then
    sleep 2
    prompt=$(osascript -e "display dialog "Are you sure? Clicking Continue will run the script and Restart this Mac. 
        " buttons {"Continue", "Cancel"} with title "$title" default button 2 with icon "$icon" ")
fi

如果Mac处于黑暗模式,那么我代码的第一行就会有

icon=(/Library/ctxsit/CompanyIconW.icns)

以上都在";工作";我的剧本版本。因此,我在";非工作";版本


接下来,不工作的部分是:

#!/bin/bash
currentOS=$(sw_vers -productVersion)
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
#mode=$(sudo -u "$currentUser" defaults read -g AppleInterfaceStyle)
OScheck=$([[ (($currentOS < 10.14)) ]]; echo $?)

function setIcon()
{
    if [[ $OScheck == "1" ]]; then
        echo "Mojave or newer"
        if [[ $mode == "Dark" ]]; then
            echo "Dark mode enabled"
            icon="CompanyIconW.icns"
        else
            echo "Light mode enabled"
            icon="CompanyIconB.icns"
        fi
    else
        echo "Older than Mojave"
        icon="CompanyIconB.icns"
    fi
}
setIcon
echo $icon
title="Company IT Notification"
echo $title
prompt=$(osascript -e "display dialog "Click Continue to logout from current user and set this Mac back to the Welcome Screen. This will leave the current user directory and profile intact.
Please make sure your work is saved. After Continuing, the device will appear to be in a Fresh OS state.  
        " buttons {"Cancel", "Continue"} with title "$title" default button 2 with icon "$icon" ")

if [[ $prompt == "button returned:Continue" ]] 
then
    sleep 2
    prompt=$(osascript -e "display dialog "Are you sure? Clicking Continue will run the script and Restart this Mac. 
        " buttons {"Continue", "Cancel"} with title "$title" default button 2 with icon "$icon" ")
fi

最后,当我从终端运行这个脚本时,我得到了这样的结果:

bash-3.2$ ./Scratch2.sh
Mojave or newer
Light mode enabled
CompanyB.icns
Company IT Notification
0:393: execution error: A resource wasn’t found. (-192)
0:134: execution error: A resource wasn’t found. (-192)

我能想到的唯一要解决的部分是;工作";版本,我有一个实际的文件路径,而我的";非工作";版本不包括那个部分。这引出了我的主要问题:

如何根据函数的返回/结果/退出代码/设置变量?

例如采用计算机处于的任何模式(亮、暗(,并使用文件1表示亮,使用文件2表示暗。

一些bash的技巧

这是另一种强有力的方法。。。

考虑一下为什么避免使用子shell是一种很好的做法,这里没有其他分叉,只有苹果二进制文件。

填充变量:

read -r currentOS < <(exec sw_vers -productVersion)
while IFS=$' :trn' read -r lhs rhs ;do
    [ "$lhs" = "Name" ] && currentUser=$rhs
done   < <(exec Scutil <<<"show State:/Users/ConsoleUser")

正在比较版本号:

compareOSver() {
    local osMaj osMin osSub cStr1 cStr2
    local -i retVal
    IFS=. read -r osMaj osMin osSub _ <<<"$1"
    printf -v cStr1 %06d "$osMaj" "$osMin" "$osSub"
    IFS=. read -r osMaj osMin osSub <<<"$2"
    printf -v cStr2 %06d "$osMaj" "$osMin" "$osSub"
    retVal="10#${cStr1} > 10#${cStr2} ? 1 : 10#${cStr2} > 10#${cStr1} ? 2 : 0"
    return $retVal
}

变量从函数传递到脚本:

function setIcon() {
    local returnVar=${1:-iconRes}
    compareOSver "$2" "$3"
    case $? in
        1 ) printf -v $returnVar 'Newer_OS.icn' ;;
        2 ) printf -v $returnVar 'Older_OS.icn' ;;
        * ) printf -v $returnVar 'Same_OS.icn' ;;
    esac
}
So you could:
setIcon icon "$currentOS" 10.14

我第一次尝试使用osascript

DialogStr='Click Continue to logout from current user and set this Mac back to 
the Welcome Screen. This will leave the current user directory and profile intact.
Please make sure your work is saved. After Continuing, the device will appear to 
be in a Fresh OS state.'
title="Company IT Notification"
printf -v osaCmd 'display dialog "%s" buttons {"Cancel","Continue"} 
        with title "%s" default button 2 with icon %d' 
        "${DialogStr//$'\\n'}" "$title" 0
IFS=: read -r _ userAnswer < <(exec osascript -e "${osaCmd//$'\\n'}")

好的,我在这里找到了:使用osascript时更改通知的图标使用备用图标的一种方式,正确的语法是icon alias "file:path:in:mac:format:icon.icn"

testIcon=/Volumes/Macintosh HD/Applications/Utilities/Terminal.app/Contents/Resources/term_icon.icns 

然后

testIcon=${testIcon#/Volumes/}
printf -v osaCmd 'display dialog "%s" buttons {"Cancel","Continue"} 
    with title "%s" default button 2 with icon alias "%s"' 
    "${DialogStr//$'\\n'}" "$title" "${testIcon////:}"
IFS=: read -r _ userAnswer < <(exec osascript -e "${osaCmd//$'\\n'}")

分配值图标的方式是"对";,但我认为你的条件表达式是错误的:

OScheck=$([[ (($currentOS < 10.14)) ]]; echo $?)

除了使用<而不是-lt之外,十进制算术在Bash中不起作用,因此您将不得不依赖bc:等外部工具

OScheck=$(echo "$currentOS < 10.14" | bc) # 1 = true, 0 = false

相应地更新您的案例陈述。

附带说明一下,icon=(/Library/ctxsit/CompanyIconB.icns)实际上与icon="CompanyIconB.icns"相同,只是第一个是对数组的显式赋值,而第二个不包括目录路径。

还要避免";返回值";使用命令替换从函数中删除,因为它效率非常低。请改用临时全局变量。

# Don't do this!
function x { echo "This is my result."; }
my_var=$(x) 
# Do this instead.
function x { __="This is my result."; }
x
my_var=$__

更新

正如评论中提到的,将版本号作为小数进行比较是不准确的,所以我建议使用一个比较它们的函数。这需要检查输入参数的格式。

function compare_versions {
    local a=${1%%.*} b=${2%%.*}
    [[ "10#${a:-0}" -gt "10#${b:-0}" ]] && return 1
    [[ "10#${a:-0}" -lt "10#${b:-0}" ]] && return 2
    a=${1:${#a} + 1} b=${2:${#b} + 1}
    [[ -z $a && -z $b ]] || compare_versions "$a" "$b"
}

最新更新