Bash – Script to quickly test all keyboard keys

awkbashgrepkeyboardstdout

I need to check some notebooks for bad keyboard keys, and so I'd like to speed that up as much as possible.

I found nothing for this specific task, so my idea is a script that reads the pressed keys and knows all the keyboard keys, so I can bash them quickly and it reports which ones are not pressed yet. I suppose I could accomplish that with either showkey or xev, grepping the output:

xev | grep keysym

Sample output:

state 0x10, keycode 46 (keysym 0x6c, l), same_screen YES,
state 0x10, keycode 33 (keysym 0x70, p), same_screen YES,
state 0x11, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
state 0x10, keycode 51 (keysym 0x5d, bracketright), same_screen YES,
state 0x10, keycode 36 (keysym 0xff0d, Return), same_screen YES,

The readable keysym is quite useful, but I keed to test keycodes, as they do not change as modifier keys are switched on/off (caps lock, num lock). I'm new to bash, so I'm putting something together. This is best result so far:

#!/bin/bash

function findInArray() {
    local n=$#
    local value=${!n}
    for ((i=1;i < $#;i++)) {
    if [[ ${!i} == ${value}* ]]; then
    echo "${!i}"
    return 0
    fi
    }
    echo
    return 1
}

list=( 38:a 56:b 54:c 40:d 26:e 36:Return 50:Shift_L )
xev | \
# old grep solution
# grep -Po '(?<=keycode )[0-9]+(?= \(keysym 0x)' | \
# 200_success' suggestion
awk '/state 0x.*, keycode / { print $4; fflush() }' | \
while read keycode ; 
do
  found=$(findInArray "${list[@]}" ${keycode})
  if [[ $found ]]; then
    echo Pressed $found
    list=(${list[@]/${keycode}\:*/})
    echo 'Remaining ===>' ${list[@]}
    if [[ ${#list[@]} == 0 ]]; then
      echo All keys successfully tested!
      pkill xev
      exit 0
    fi
  fi
done

While I used grep it was only printing the output when I closed xev and it wouldn't kill it at the end too. The awk suggestion from @200_success solved these issues, but it does not print the output immediatelly: it takes 5-6 keystrokes for the output to be "flushed". How can I fix that?

Note: I know that this script would require a different list of keys for each different model of keyboard, but this is OK, as I only have a couple models to test.


Edit 1: I edited the question with my latest script code.

Edit 2: script updated according to @200_success suggestion.

Best Answer

Try replacing your grep line with an awk script that flushes its output.

xev | \
awk '/state 0x.*, keycode / { print $4; fflush() }' | \
while read keycode ; do
    # etc.
done
Related Question