Home > Mobile >  Bash Scripting - How can I use a function to determine whether my variable will use file 1 or file 2
Bash Scripting - How can I use a function to determine whether my variable will use file 1 or file 2

Time:01-01

I am quite new here but have learned so much in the last few months. I'm really getting into this. That said, my Stack Overflow searches seem to only end up with more questions, at the moment.

What I am trying to do is (in Mac OS X / MacOS) create a dialog in using osascript. I'd like to add an icon to it. This part is easy and works.

However, the problem is that if the user is in dark or light mode my icon file won't look right. So, i've got two .icns files which is stored on all Macs in my environment in a specific directory (that directory is located at /Library/ctxsit/). I can call up one or the other using a variable, but when I add a function to determine which file to use, it fails.

First, the part that works is:

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

If the Mac is in Dark mode, then that first line of my code would have

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

All above is in the "working" version of my script. So, I have added a function to the "non-working" version. Next, the part which does not work is:

#!/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

Finally, when I run this script from terminal, I get this result:

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)

I hope this question wasn't too long and convoluted. I know only enough to find more that I don't know at each turn haha. Please let me know if you'd like some context or even the file itself (i have a few additional working if/else loops after the ones posted here, but that is the part that works.)

The only part I can think of to address is how in my "working" version, I have an actual path-to-file whereas my "non-working" version does not include that piece. This leads to my main question:

How can I set a variable based off of the return/result/exit code/ of a function?

e.g. take whichever mode this computer is in (light,dark) and use file 1 for light and file 2 for dark.

Anyways, thanks for your help!

Best,

New Guy

CodePudding user response:

The way you assign the value icon is "right", but I think your condition expression is wrong:

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

Besides the fact that you use < instead of -lt, decimal arithmetic doesn't work in Bash, so you would have to rely on external tools like bc:

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

Update your case statement accordingly.

As a side note, icon=(/Library/ctxsit/CompanyIconB.icns) is virtually the same as icon="CompanyIconB.icns" except the first one is an explicit assignment to an array, and the second one does not include a directory path.

Also avoid "returning values" from a function by using command substitution as it is terribly inefficient. Use a temporary global variable instead.

# 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=$__

Update

As mentioned in the comments, comparing version numbers as decimals is not accurate, so I suggest using a function that compares them. This needs format of input arguments checked.

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"
}

CodePudding user response:

Some bash's trick

Here is other robust way for doing this...

Populating variables:

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

Comparing version number:

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

Passing variable from function to script:

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

My first tries using 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 < <(osascript -e "${osaCmd//$'\\\\\n'}")
  • Related