You can use the script as above. Perhaps a little explanation might help make sense out of it:
Long script explanation (click to expand).
I’ll go through it line by line (except for the comments, i.e. the ones that start with #
) so you can understand what’s going on.
#!/bin/bash
This is called the shebang and basically instructs the shell to use this program to run the script. In general, it will come in this format, but I prefer #!/usr/bin/env bash
because it’s a bit more portable, but it’s fine as is.
echo 'touchpad.sh: DEBUG: entering'
This and other similar lines merely output the quoted text. The purpose for this is to allow for one to understand where one is in the program execution. This is useful for debugging. Since you are not debugging, you can either leave these out or comment them. I will not comment on similar lines.
MY_TOUCHPAD_ID="$(xinput list | grep -i touchpad | cut -d'=' -f2 | cut -d$'\t' -f1)"
This assigns a variable, MY_TOUCHPAD_ID
with the output of the string of commands inside of the parentheses. This is called command substitution. The pipes (|
) take the output of the previous command and feed it into the input of the next command and each of those commands are as such:
xinput list
lists all of the input devices
grep -i touchpad
does a case insensitive (that’s the -i
) search for any instance of the word touchpad
in the above and outputs the result
cut -d'=' -f2
print the field (that’s the -f
, with the 2 specifying the second field) after =
in the above. Our first command has an output that includes only one such delimiter (that’s the -d
), the device ID.
cut -d$'\t' -f1
prints the field before a TAB character. Since the first command includes a master/slave description after the ID, we need to remove this to isolate the ID.
if [ "$MY_TOUCHPAD_ID" == "" ]; then
This uses the conditional if-clause to test if the MY_TOUCHPAD_ID
variable (by the way, the $
before the variable outputs its value and is called parameter expansion) is empty.
exit
This exits the program, in the case that the variable is empty, as it means we don’t have a touchpad we can identify, so we shouldn’t go trying to tweak settings on it.
fi
This ends the if-clause.
if [ "$1" == "" ]; then
Another if-clause, but this is checking to see if the first positional parameter or argument to the program is empty. This allows for calling the program in the form touchpad.sh
to toggle the state rather than explicitly specifying the state with the 0 or 1 argument (e.g. touchpad.sh 0
turns it off).
MY_TOUCHPAD_STATE="$(xinput list-props $MY_TOUCHPAD_ID | grep -i "tapping enabled" | cut -f3)"
This creates a new variable, MY_TOUCHPAD_STATE
that lists the properties of of our touchpad (by ID, using the MY_TOUCHPAD_ID
variable from before), then searches for tapping enabled
and using the TAB character as a delimiter (though it’s not specified, it’s the default for cut
), outputs the third field. This is the value of the “tapping enabled” property, a 0 or 1 value.
if [ "$MY_TOUCHPAD_STATE" == "0" ]; then
MY_TOUCHPAD_STATE="1"
This checks if the state is 0, and if so, sets it to 1.
elif [ "$MY_TOUCHPAD_STATE" == "1" ]; then
MY_TOUCHPAD_STATE="0"
This is another form of the if-clause, but one that’s nested within the clause itself. It can be read “else-if.” It checks to see if the state is 1, and if so, sets it to 0.
else
echo "touchpad.sh: ERROR: Could not find current touchpad status (to toggle). Setting to enabled."
MY_TOUCHPAD_STATE="1"
This is another option in the if-clause: an option to match anything that didn’t meet the previous tests. In this case, it means the state was something other than 0 or 1, which is erroneous. The script chooses to arbitrarily set it to 1 to at least return it to a normal state.
elif [ "$1" != "0" ] && [ "$1" != "1" ]; then
echo "touchpad.sh: ERROR: Passed argument not 0 or 1. Setting to 1."
MY_TOUCHPAD_STATE="1"
I’m not sure you noticed it but there is actually a whole if-clause (i.e. if
…fi
) nested within another one. The first one checked if the first argument was empty and used the second if so. This returns back to that if-clause. In the event the argument is not empty, then it checks if it is something other than 0 or 1. If this is the case, just like the last error check, this sets it to 1.
else
MY_TOUCHPAD_STATE="$1"
We’ve tested if the first argument was empty and if it was not 0 or 1, which leaves us the only other real options: it’s either 0 or 1. In that case, the script was run with a request for an explicit state. This sets our state variable to that argument.
xinput set-prop $MY_TOUCHPAD_ID "Tapping Enabled" $MY_TOUCHPAD_STATE
Now that we have our ID and we have our state, we can simply set it using those variables.
I hope that helps you better understand how the script works and will help you in creating future scripts. The key is that the touchpad ID is acquired generally and the property is defined more generally rather than by its ID.
One thing to consider is that it really doesn’t hurt to set a property to a value it already has. That said, you can also summarize it into two really long commands: