4

My intended goal is to create a script that when run, will check the state of a setting, then change it to the opposite state. The setting in question is regarding the manual or disabled state of proxy settings in Ubuntu's settings.

I can manually obtain the state of this setting with the command:

gsettings get org.gnome.system.proxy mode

This will return auto, manual, or none. I don't use the first state, so let's ignore that from here on. Now, once the state is returned, my goal with the script is to then run either one of the following commands:

gsettings set org.gnome.system.proxy mode 'manual'
gsettings set org.gnome.system.proxy mode 'none'

The command it runs will be the state not currently set. To that end, I have attempted the following in a script:

if [ 'gsettings get org.gnome.system.proxy mode' = 'none' ]
then
gsettings set org.gnome.system.proxy mode 'manual'
notify-send "Manual"
else
if [ 'gsettings get org.gnome.system.proxy mode' = 'manual' ]
then
gsettings set org.gnome.system.proxy mode 'none'
notify-send "Disabled"
fi
fi

This is saved in a file with chmod +x applied. When run from the terminal, nothing happens. I just get a new line to await a new command.

Where have I gone wrong?

In addition, is it possible to get this to work on a single line, like so:

sh -c "if [ $(gsettings get org.gnome.system.proxy mode) = \"'none'\" ];then gsettings set org.gnome.system.proxy mode 'manual' && notify-send \"Manual\";elif [ $(gsettings get org.gnome.system.proxy mode) = \"'manual'\" ];then gsettings set org.gnome.system.proxy mode 'none' && notify-send \"Disabled\";fi"

Again, same (lack of) results.

hiigaran
  • 6,473
  • 4
  • 28
  • 40
  • 3
    You need "$(gsettings get org.gnome.system.proxy mode)" to get the output of gsettings get org.gnome.system.proxy mode. 'gsettings get org.gnome.system.proxy mode' is just the string 'gsettings get org.gnome.system.proxy mode'. – muru Oct 18 '18 at 05:39
  • 1
    Perfect, thanks. Also discovered the value returned is already enclosed in single quotes, so I needed to enclose double quotes around the expected values. – hiigaran Oct 18 '18 at 05:50
  • Is this script possible to run from a single line of code? I've edited in what I tried at the end of my question. – hiigaran Oct 18 '18 at 06:19
  • Possible? Probably, but in a horribly ugly way. Best put it in a script somewhere instead. – muru Oct 18 '18 at 06:22
  • I was hoping to avoid making a script file. Not a massive deal, I guess. It's just a preference, even if it is ugly. – hiigaran Oct 18 '18 at 06:26
  • 1
    If you must: sh -c 'case $(gsettings get org.gnome.system.proxy mode) in *none*) mode="$1";; *) mode="$2";; esac; gsettings set org.gnome.system.proxy mode "$mode"' _ manual none – muru Oct 18 '18 at 06:30
  • You might be right about sticking to script files. I'll have to look into the usage of case and esac, but for the time being, perhaps files might be better. Thanks. – hiigaran Oct 18 '18 at 07:04

2 Answers2

1

The if statement is appropriate tool in this case, however, consider as alternative case statement for single-run of the command in question and arguably cleaner syntax.

case "$(gsettings get org.gnome.system.proxy mode)" in

    "'none'") gsettings set org.gnome.system.proxy mode "'manual'" 
              notify-send "manual";;
    "'manual'") gsettings set org.gnome.system.proxy mode  "'none'"
                notify-send "Disabled" ;;

esac

Note that the gsettings get command in question returns single-quoted strings so you do need to check for that.

As for your specific code, the issue is that you're doing string comparison, but you really need command-substitution $()

if [ "$(gsettings get org.gnome.system.proxy mode)" = "'none'" ]
then
    gsettings set org.gnome.system.proxy mode "'manual'"
    notify-send "Manual"
elif [ "$(gsettings get org.gnome.system.proxy mode)" = "'manual'" ]
then
    gsettings set org.gnome.system.proxy mode "'none'"
    notify-send "Disabled"
fi

This is your code edited. Note that the syntax also was not correct, there's no else if but there's elif in shell syntax. Additionally, the two tests call same command twice. This is not efficient. Use single command substitution as shown in Gavin's answer

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
  • I was able to figure this one out a while back from the comments in my question, but I do like your case statement alternative. The syntax throws me off, however. I understand most of the structure, but why is there a ) without a ( on the 3rd and 5th lines? Also, why are there two semicolons next to each other? – hiigaran Dec 11 '18 at 04:15
  • 1
    @hiigaran While I don't know the answer to why ) was chosen, I can speculate about it from this point of view: in a lot of programming languages, switch-case statement has syntax of case : action ;, but when original bourne shell was created : was used originally as goto statement ( see the answer on topic ) , so Steven Bourne had to choose something else. The ; designates end of command or in compound statements like if and for serves same as newline - statement separator. So ;; is case terminator, since ; is already taken – Sergiy Kolodyazhnyy Dec 11 '18 at 04:34
  • 1
    @hiigaran As for missing ( that's because ( designates subshell, so can't use that – Sergiy Kolodyazhnyy Dec 11 '18 at 04:34
0

Your problem is that you cannot use a command in an if/then statement.

Here is the fixed code:

#!/bin/bash
output=$(gsettings get org.gnome.system.proxy mode)
if [ "$output" = 'none' ]
then
    gsettings set org.gnome.system.proxy mode 'manual'
    notify-send "Manual"
else
    if [ "$output" = 'manual' ]
    then
        gsettings set org.gnome.system.proxy mode 'none'
        notify-send "Disabled"
    fi
fi
  • 1
    Technically, you can use commands in if-then statement. if command; then structure operates on exit status of commands. However, if we're concerned with output of a command then if [ "$(command)" = "output" ]; then is necessary. And yes, [ is a command, in most modern shells it's a built in although it exists as standalone /usr/bin/[ or /usr/bin/test on Linux. Depending on the comparison, it returns appropriate exit status which serves as entry point for if or else part of the block – Sergiy Kolodyazhnyy Dec 11 '18 at 00:56
  • Learn something new everyday – Gavin Morton Dec 11 '18 at 12:46