2

Where am I going wrong in this Bash?

declare current_state=`pacmd list-sources | sed -n 19p`
declare my_target='used by: 0'
echo $current_state = $my_target
if [ '$current_state' = '$my_target' ] ; then
    echo true
    pacmd set-default-sink "alsa_output.pci-0000_0c_00.4.analog-stereo"
    echo true
else
    echo false
    pacmd set-default-sink "alsa_output.pci-0000_0a_00.1.hdmi-stereo-extra2"
    echo false
fi

It is always outputting the else (false) option to terminal:

used by: 0 = used by: 0
false
false

I have tried if [[ '$current_state' = '$my_target' ]] , if [[ '$current_state' == '$my_target' ]], if [ '$current_state' == '$my_target' ], if [ '$current_state' == 'used by 0:' ], if [ '$current_state' = 'used by 0:' ], etc. It's always coming back as false.

For context, I was trying to use scripts from How to switch sound output with key shortcut but none of those work because my output indeces are 2, 3, and 30. Because that makes sense. Anyway, I found by running the pacmd list-sources while varying the manually selected outputs out of Sound Settings differences in a few lines. (Line 6 was what I initially tried, and it would report the status of one of index 2 (the first one, yes, the first) as state: IDLE, state: RUNNING, or state: SUSPENDED.) I managed to make the bash script work once to change from my headphones to my monitor, and then no more. So I tried changing where I look to this line 19 output which tells me if it's in use (I think) with either used by: 1 when active or used by: 0 when inactive to just toggle. But nope, no luck.

So then I get into the basic troubleshooting to make sure my if/else is evaluating correctly, and it's not. I don't know what I'm supposed to do here. Did I screw something up with declare?? I don't know.

Tim50001
  • 65
  • 7
  • 1
    "$current_state" = "$my_target" ... Use double quotes " around variables .... Single quotes prevent their expansion. – Raffa Nov 26 '22 at 18:03
  • @Raffa no luck in doing that. Just made that single change from the code originally posted, and it's still evaluating as false. – Tim50001 Nov 26 '22 at 18:12
  • @steeldriver using that site I can get code that says there are No issues detected! with this code. And it still doesn't work.
    #!/bin/bash
    
    current_state=$(pacmd list-sources | sed -n 19p)
    my_target="used by: 0"
    echo "$current_state" = "$my_target"
    if [ "$current_state" = "$my_target" ] ; then
     echo true
     pacmd set-default-sink "alsa_output.pci-0000_0c_00.4.analog-stereo"
     echo true
    else
     echo false
     pacmd set-default-sink "alsa_output.pci-0000_0a_00.1.hdmi-stereo-extra2"
     echo false
    fi
    
    – Tim50001 Nov 26 '22 at 18:16
  • 1
    pacmd list-sources usually results in lines with leading spaces/tabs ... That might result in the two strings you are comparing to be not equal ... Spaces count. – Raffa Nov 26 '22 at 18:23
  • @Raffa that helped. The problem is I used = instead of =. By removing the surrounding spaces on the equivalence operator, it worked. At least to evaluate as true. I still have work to do on my troubleshooting, as it isn't doing a toggle. I'll have to explore a persistent variable as a toggle I think as my answer, rather than reading an output. – Tim50001 Nov 26 '22 at 18:35
  • 1
    You can use =~ for partial match e.g. try [ " abc: 1" = "abc: 1" ] && echo "full match" || [[ " abc: 1" =~ "abc: 1" ]] && echo "partial match" ... notice the order of string and sub-string around =~ and the use of [[ ... ]] – Raffa Nov 26 '22 at 18:38
  • 1
    You need the spaces around = i.e. "abc" = "abc" or otherwise it will evaluate true always e.g. "abc"="abcd" will evaluate true. – Raffa Nov 26 '22 at 18:52

1 Answers1

2

pacmd list-sources usually results in lines with leading spaces/tabs ... That might result in the two strings you are comparing to be not equal ... Spaces count.

You can use =~ for partial match e.g. try [ " abc: 1" = "abc: 1" ] && echo "full match" || [[ " abc: 1" =~ "abc: 1" ]] && echo "partial match" ... notice the order of string and sub-string around =~ and the use of [[ ... ]]

So modifying your code:

#!/bin/bash

current_state=$(pacmd list-sources | sed -n 19p) my_target="used by: 0" echo "$current_state" = "$my_target" if [[ "$current_state" =~ "$my_target" ]] ; then echo true pacmd set-default-sink "alsa_output.pci-0000_0c_00.4.analog-stereo" echo true else echo false pacmd set-default-sink "alsa_output.pci-0000_0a_00.1.hdmi-stereo-extra2" echo false fi

Raffa
  • 32,237
  • Thanks for correcting my mistake. I'd have been banging my head on that for a few hours when I always got a true evaluation. And thanks for teaching that [[ ]] is necessary for =~; I tried to use the regex match operator and got an error with [ ].

    This seems to work other than now after waking my computer up from sleep the output devices have been renamed and reindexed (2, 3, and now 47.)

    – Tim50001 Nov 26 '22 at 23:03