A mouse click sends 6 characters: ESC, [, M, , , . The first 3 characters are common to all mouse events, the second 3 contain the button pressed, and the x and y locations of the mouse. To confirm this, I saved the input in a variable and piped it to hexdump: $ printf "\e[?9h" $ read x ^[[M!MO $ printf "$x" | hexdump -C 00000000 1b 5b 4d 21 4d 4f |.[M!MO| 00000006 The first 3 appear as expected, but what are the final 3? According to the man page, the lower 2 bits of the button character tell which button has been pressed; the upper bits identify the active modifiers. The x and y coordinates are the ASCII values to which 32 has been added to take them out of the range of control characters. ! is 1, " is 2, etc.. That gives us a 1 for the mouse button (which means button 2, since 0 to 2 are buttons 1, 2, and 3 respectively, and 4 is release). The x and y coordinates are 45 ( M=77; 77−32=45) and 47. Surprisingly, since I read about mouse tracking in a Linux console_codes man page, these escape codes do not work in any Linux console that I have tried. They work in xterm, rxvt, and gnome-terminal on Linux and FreeBSD. I've used them on FreeBSD and NetBSD, via ssh from a Linux rxvt terminal window. They do not work in a konsole window. We now know that mouse reporting works (in most xterm windows), and we can get information from a mouse click on the standard input. That leaves two questions: how do we read the information into a variable (without having to press return), and how can the button and x,y information be decoded in a shell script? With bash, the read command can take an argument to specify the number of characters: read -sn6 x More portably, stty and dd can be used: _STTY=$(stty -g) ## Save current terminal settings printf "\e[?9h" ## Turn on mouse reporting stty -echo -icanon ## Turn off echo and line buffering, x=$(dd bs=1 count=6 2>/dev/null) ## Read six characters echo "$x" | hexdump -C ## Display the characters in hex printf "\e[?9l" ## Turn off mouse reporting stty "$_STTY" ## Restore terminal Neither of these is adequate for a real script (not all input will be mouse clicks, and we will want to get single keystrokes), but these suffice to demonstrate the concept. The next step is to decode the input. For the purpose of this demonstration, we will assume that the 6 characters do indeed represent a mouse click, and that the first 3 characters are ESC, [, and M. We are only interested in the last 3, so we extract them into three separate variables using POSIX parameter expansion: m1=${x#???} ## Remove the first 3 characters m2=${x#????} ## Remove the first 4 characters m3=${x#?????} ## Remove the first 5 characters Then we convert the first character of each variable to its ASCII value. This uses a POSIX printf extension, "If the leading character is a single-quote or double-quote, the value shall be the numeric value in the underlying codeset of the character following the single-quote or double-quote." Since command substitution is slow in all shells except KornShell93, the 3 assignments are grouped in a single eval statement: eval "$(printf "mb=%d mx=%d my=%d" "'$m1" "'$m2" "'$m3")" Finally, we interpret the ASCII values. For the mouse button, we do a bitwise AND 3. For the x and y coordinates, we subtract 32: ## Values > 127 are signed, so fix if less than 0 [ $mx -lt 0 ] && mx=$(( 255 + $mx )) [ $my -lt 0 ] && my=$(( 255 + $my )) BUTTON=$(( ($mb & 3) + 1 )) MOUSEX=$(( $mx - 32 )) MOUSEY=$(( $my - 32 )) Putting it all together, the script in Listing 1 prints the mouse's coordinates at that location whenever you press a mouse button. There are 2 buttons on the top row. Clicking the left button toggles the mouse reporting mode between reporting only a button press and reporting the release as well. Clicking the right-hand button exits the script. You can add a button to clear the screen by making two simple changes to the script. Change: print_buttons "$mv_str" "Exit" to: print_buttons "$mv_str" "Clear" "Exit" and: 2) break ;; to: 2) clear ;; 3) break ;;