I want to name a (USB) device persistently depending on the port it is connected to.

Using udevadmin I found the following info

# udevadm info --name=input/event3 | grep ID_PATH
E: ID_PATH=platform-ci_hdrc.1-usb-0:1.1.4:1.0
E: ID_PATH_TAG=platform-ci_hdrc_1-usb-0_1_1_4_1_0

So the device seems to have properties ID_PATH and ID_PATH_TAG, which look like what I want.

I added to a matching udev.rule

SYMLINK+="foo-%E{ID_PATH_TAG} foo1-$env{ID_PATH} foo2-$env{ID_PATH_TAG}"

(The 3 variants were just trying desperately... one should be enough once it works.)

The rule gets executed and the there is no error in the log (log level = debug).

However, the created symbolic links are called


So it looks like the properties ID_PATH and ID_PATH_TAG are not yet set when my rule gets executed. Do I need to pay attention to any ordering?


First run this command to get the list of attributes of your device.

udevadm info -a -p $(udevadm info -q path -n <devpath>)

then you can do something like this

... SYMLINK+=”device_$attr{serial}”, ...

sometimes you have to set a environment variable with the data that you need, something like this.

... ENV{SERIAL_NUMBER}="$attr{serial_number}"

to later use it like this.

... SYMLINK+="device_$env{SERIAL_NUMBER}"
  • What is exactly the difference between an environment variable and an attribute? If there is an attribute, why would I want to set an environment variable first and then use it later instead of just using the attribute in the first place? My udevadm info output showed E:, so I'm guessing ID_PATH is an environment variable. – Uwe Geuder Sep 22 '15 at 6:04

I saw that existing rules using ID_PATH are all 60-* or higher. Mine was 45-* for no particular except historic reasons.

Renaming my rules file shows that it's the rule number that makes the difference:

  1. 59-foo.rules: ID_PATH/ID_PATH_TAG expand to empty string
  2. 60-foo.rules: ID_PATH/ID_PATH_TAG expand to empty string
  3. 61-foo.rules: ID_PATH/ID_PATH_TAG expand correctly

The explanation is in 60-persistent-input.rules containing

SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id"

I could not find documentation for the builtins, but I'm guessing that the path_id builtin puts ID_PATH/ID_PATH_TAG into the environment.

  • You can also bring in the path's by adding this just above the SUBSYSTEMS line: ENV{ID_PATH}=="", IMPORT{builtin}="path_id" – joshperry Oct 17 '17 at 3:31
  • Yeah it sounds logical that that should work. However, I would not see a good reason to duplicate that code into my own "earlier" rule, if the distro already contains the same code in a "later" rule. – Uwe Geuder Oct 17 '17 at 23:07
  • Agreed. FYI, saw this technique here: lists.debian.org/debian-user/2017/07/msg01453.html – joshperry Oct 19 '17 at 3:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.