Summarizing the Simon Rigét answer , I came up with this bash function, which, given the optional vendor identifier and product identifier, returns a list of node device names associated with this vendor identifier and product identifier, if one is specified.
getDevNodes() { if [ -n "$1" ] && [ "$1" != "no_class" ]; then 2>/dev/null find -L /sys/class/$1 -maxdepth 2 -mindepth 2 -name uevent -exec realpath "{}" + else find /sys/devices -name uevent fi | { if [ -z "$1" ]; then readarray -t lines < <(find /sys/class -maxdepth 2 -mindepth 2 -type l -print -exec realpath "{}" +) local -i count=${#lines[@]} sys_dev=count/2 sys_class=0 local -A classes while [ $sys_dev -lt $count ]; do class="${lines[$sys_class]#/*/*/}" class="${class%/*}" classes["${lines[$sys_dev]}"]="$class" sys_dev+=1 sys_class+=1 done fi readarray -t uevents for u in "${uevents[@]}"; do DEVNAME=; DEVTYPE=no_type; while IFS="=" read key value; do { [ "$key" = "DEVNAME" ] && DEVNAME=/dev/"$value" } || { [ "$key" = "DEVTYPE" ] && DEVTYPE="$value" }; done < "$u" if [ -n "$DEVNAME" ]; then path="${u%/uevent}" while [ "$path" != "/sys/devices" ] && ! [ -f "$path"/idVendor ]; do path="${path%/*}" done [ "$path" != "/sys/devices" ] && { read readIdVendor < "$path"/idVendor read readIdProduct < "$path"/idProduct } || { readIdVendor=---- readIdProduct=---- } echo "${1:-${classes[${u%/uevent}]:-no_class}}" "$DEVTYPE" "$readIdVendor" "$readIdProduct" "$DEVNAME" fi done } | grep "^${1:-[[:graph:]]\+} ${2:-[[:graph:]]\+} ${3:-....} ${4:-....}" | cat }
For example, this is what my lususb says:
$ lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 008: ID 0bda:b719 Realtek Semiconductor Corp. Bus 001 Device 006: ID 0bda:57b5 Realtek Semiconductor Corp. Bus 001 Device 004: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller Bus 001 Device 097: ID 1004:6344 LG Electronics, Inc. G2 Android Phone [tethering mode] Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
So, if I wanted to see which device nodes are associated with the vendor identifier 0x1004 and product identifier 0x6344, I would do the following:
$ getDevNodes "" "" 1004 6344 no_class usb_device 1004 6344 /dev/bus/usb/001/097 tty no_type 1004 6344 /dev/ttyACM0
So, we have two device nodes, one of which has a tty class without devtype, and the other an unknown class, but with devtype usb_device.
You can also specify a vendor identifier, for example:
$ getDevNodes "" "" 0bda no_class usb_device 0bda 0129 /dev/bus/usb/001/004 no_class usb_device 0bda b719 /dev/bus/usb/001/008 no_class no_type 0bda 57b5 /dev/media0 video4linux no_type 0bda 57b5 /dev/video0 input no_type 0bda 57b5 /dev/input/event14 no_class usb_device 0bda 57b5 /dev/bus/usb/001/006
If I only need devices of the video4linux class whose seller ID is 0bda, I would do the following:
$ getDevNodes video4linux "" "" 0bda video4linux no_type 0bda 57b5 /dev/video0
Arguments are basically filters over the entire list of device nodes and their associated information. Omitting one of these arguments or using the empty string "" as an argument disables the filter for this particular argument.
The arguments are given in the following order: 1: class, 2: type, 3: vendor identifier, 4: product identifier.
Here is an example of a lightweight version of the above function, which runs faster due to some functions: the device nodes are printed without additional information, and there is no filter for the device type.
getDevNodesLite() { if [ -n "$1" ]; then 2>/dev/null find -L /sys/class/$1 -maxdepth 2 -mindepth 2 -name uevent -exec realpath "{}" + else find /sys/devices -name uevent fi | { if [ -n "$2" ]; then readarray -t uevents for u in "${uevents[@]}"; do path="${u%/uevent}" while [ "$path" != "/sys/devices" ] && ! [ -f "$path"/idVendor ]; do path="${path%/*}" done [ "$path" != "/sys/devices" ] && read readValue < "$path"/idVendor && [ "$readValue" = "$2" ] && { if [ -n "$idProduct" ]; then read readValue < "$path"/idProduct && [ "$readValue" = "$3" ] fi } && echo "$u" done else cat fi } | { readarray -t uevents [ ${#uevents[@]} -gt 0 ] && sed -n 's,DEVNAME=\(.*\),/dev/\1,p' "${uevents[@]}" } }