Обобщая ответ Саймона Ригета , я придумал эту функцию bash, которая при наличии необязательного идентификатора поставщика и идентификатора продукта возвращает список имен узлов устройства, связанных с идентификатором этого поставщика и идентификатором этого продукта, если он указан .
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
}
Например, вот что говорит мне мой lsusb:
$ 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
Итак, если бы я хотел увидеть, какие узлы устройства связаны с идентификатором поставщика 0x1004 и идентификатором продукта 0x6344, я бы сделал следующее:
$ getDevNodes "" "" 1004 6344
no_class usb_device 1004 6344 /dev/bus/usb/001/097
tty no_type 1004 6344 /dev/ttyACM0
Итак, у нас есть два узла устройства, один из которых имеет класс tty без devtype, а другой - с неизвестным классом, но с devtype usb_device .
Можно также указать только идентификатор поставщика, например:
$ 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
Если бы я хотел только video4linux класса устройств с идентификатором поставщика 0bda, то я бы сделал следующее:
$ getDevNodes video4linux "" "" 0bda
video4linux no_type 0bda 57b5 /dev/video0
Аргументы в основном фильтруют полный список узлов устройств и связанную с ними информацию. Пропуск одного из этих аргументов или использование пустой строки "" в качестве аргумента отключает фильтр для этого конкретного аргумента.
Аргументы приводятся в следующем порядке: 1: класс, 2: тип, 3: идентификатор поставщика, 4: идентификатор продукта.
Ниже приведена облегченная версия вышеуказанной функции, которая работает быстрее за счет некоторых функций: узлы устройства печатаются без дополнительной информации, и нет фильтра для типа устройства.
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[@]}"
}
}