Get device node by major/minor numbers pair












11















Each device node under /dev has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat, like this:



stat -c 'major: %t minor: %T' <file>


Or, ls -l also shows these numbers.



But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l + awk trick, but I really hope there is better solution.










share|improve this question























  • @mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

    – Dmitry Frank
    Aug 23 '14 at 20:21


















11















Each device node under /dev has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat, like this:



stat -c 'major: %t minor: %T' <file>


Or, ls -l also shows these numbers.



But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l + awk trick, but I really hope there is better solution.










share|improve this question























  • @mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

    – Dmitry Frank
    Aug 23 '14 at 20:21
















11












11








11


3






Each device node under /dev has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat, like this:



stat -c 'major: %t minor: %T' <file>


Or, ls -l also shows these numbers.



But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l + awk trick, but I really hope there is better solution.










share|improve this question














Each device node under /dev has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat, like this:



stat -c 'major: %t minor: %T' <file>


Or, ls -l also shows these numbers.



But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l + awk trick, but I really hope there is better solution.







udev






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Aug 23 '14 at 18:51









Dmitry FrankDmitry Frank

1,20361931




1,20361931













  • @mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

    – Dmitry Frank
    Aug 23 '14 at 20:21





















  • @mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

    – Dmitry Frank
    Aug 23 '14 at 20:21



















@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

– Dmitry Frank
Aug 23 '14 at 20:21







@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!

– Dmitry Frank
Aug 23 '14 at 20:21












5 Answers
5






active

oldest

votes


















7














I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.



So for example,



  for file in $(find /sys/dev/ -name 7:0); do  
source ${file}/uevent; echo $DEVNAME;
done;


Echoes,



loop0
vcs


Note: This was tested in Debian Wheezy






share|improve this answer
























  • to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

    – BBK
    Jan 23 '15 at 21:03





















5














Not sure what you mean.



mknod foo b 8 0


Will create the device file called foo as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev that have the same type, major and minor, you can do (with zsh):





  • For block device 8:0:



    $ zmodload zsh/stat
    $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
    lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
    lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
    brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda



  • for char device 226:0:



    $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
    lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
    crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0



Note that anything can create files in /dev. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc.



On modern versions of Linux, it's usually udev based on input from the kernel.



The name it chooses for the base device file is based on the DEVNAME supplied by the kernel. udev rules may change that but generally don't, and some udev rules will add some more symlinks for convenience (like the /dev/disk/by... ones).



You can go from major:minor to kernel DEVNAME by looking at:



$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0


You can also get that information from the udev database as mikeserv has shown.






share|improve this answer

































    5














    Apparently it can be done more simply with udevadm, and I've just found out how.



    To get the DEVNAME from udevadm you need only do:



    udevadm info -rq name $PATH


    For instance, if you wanted to know the /dev name for /sys/dev/char/5:1 you'd do:



    udevadm info -rq name /sys/dev/char/5:1


    OUTPUT



    /dev/console


    The -r option is to specify a --rooted path - without it the result above would read only console. The -q option specifies a database --query and it takes the operand name here - because we want the DEVNAME.



    A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:



    mmdev() for d in /sys/dev/[cb]*/$1:$2
    do [ -e "$d" ] || return
    printf %c:%s: "${d#/*/*/}" "${d##*/}"
    udevadm info -rq name "$d"
    done


    So running:



    mmdev 8 0


    prints...



    b:8:0:/dev/sda


    Here's the first one I wrote.



    majminpath() {
    set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
    udevadm info --export-db |
    sed 's|^[^=]*DEVNAME=||
    |^[^/]|!h;/MAJOR=/N
    |='"$1n.*=${2?}"'$|!d;g'
    }


    This just scans udevadm info --export-db output for the matching numbers. The output looks like:



    P: /devices/virtual/vc/vcsa4
    N: vcsa4
    E: DEVNAME=/dev/vcsa4
    E: DEVPATH=/devices/virtual/vc/vcsa4
    E: MAJOR=7
    E: MINOR=132
    E: SUBSYSTEM=vc

    P: /devices/virtual/vc/vcsa5
    N: vcsa5
    E: DEVNAME=/dev/vcsa5
    E: DEVPATH=/devices/virtual/vc/vcsa5
    E: MAJOR=7
    E: MINOR=133
    E: SUBSYSTEM=vc

    #...and so on


    The workflow is like:




    • attempt to strip the [^=]*DEVNAME= string from the head of each line


    • if a line does not have a first character or its first character is / copy that line over hold space


    • if a line matches MAJOR= append Next input line to pattern space


    • if there are 2 lines in pattern space that match =$1n.*=$2$ then copy hold space over pattern space and auto-print; else delete pattern space



    So if I do:



    majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1


    OUTPUT



    /dev/vcsa5
    /dev/sda
    /dev/sda1


    But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.






    share|improve this answer





















    • 1





      Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

      – xae
      Aug 23 '14 at 19:55











    • I gotta check subsystem - that's right. Thanks, @xae.

      – mikeserv
      Aug 23 '14 at 20:03



















    1














    Alas, the /sys/dev hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.



    Let $M and $m, respectively, be the major and minor number of our device file.




    Post 2.6.27 kernels



    As suggested by others, the simplest approach unleashes the power of the sysfs “virtual” file system, by chasing straight for files named $M:$m under the folder /sys/dev (more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent file (in a subshell so as to prevent namespace pollution):



    for file in $(find /sys/dev/ -name $M:$m)
    do
    (
    source ${file}/uevent
    echo $DEVNAME
    )
    done



    Pre 2.6.27 kernels



    Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m throughout the /sys/block hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev. If /sys/block/<...>/<DEV>/dev is one such file, then DEV is bound to be our device's name:



    dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"





    share|improve this answer































      0














      On Linux it is possible to take advantage of certain files in /proc virtual filesystem.



      $ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions 
      8 1 29309568 sda1

      $ grep '8:1[[:blank:]]' /proc/self/mountinfo
      28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered


      The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.






      share|improve this answer























        Your Answer








        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "106"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: false,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f151812%2fget-device-node-by-major-minor-numbers-pair%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        7














        I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.



        So for example,



          for file in $(find /sys/dev/ -name 7:0); do  
        source ${file}/uevent; echo $DEVNAME;
        done;


        Echoes,



        loop0
        vcs


        Note: This was tested in Debian Wheezy






        share|improve this answer
























        • to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

          – BBK
          Jan 23 '15 at 21:03


















        7














        I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.



        So for example,



          for file in $(find /sys/dev/ -name 7:0); do  
        source ${file}/uevent; echo $DEVNAME;
        done;


        Echoes,



        loop0
        vcs


        Note: This was tested in Debian Wheezy






        share|improve this answer
























        • to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

          – BBK
          Jan 23 '15 at 21:03
















        7












        7








        7







        I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.



        So for example,



          for file in $(find /sys/dev/ -name 7:0); do  
        source ${file}/uevent; echo $DEVNAME;
        done;


        Echoes,



        loop0
        vcs


        Note: This was tested in Debian Wheezy






        share|improve this answer













        I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.



        So for example,



          for file in $(find /sys/dev/ -name 7:0); do  
        source ${file}/uevent; echo $DEVNAME;
        done;


        Echoes,



        loop0
        vcs


        Note: This was tested in Debian Wheezy







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 23 '14 at 21:01









        xaexae

        1,40376




        1,40376













        • to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

          – BBK
          Jan 23 '15 at 21:03





















        • to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

          – BBK
          Jan 23 '15 at 21:03



















        to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

        – BBK
        Jan 23 '15 at 21:03







        to find backwards from dev name: for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;

        – BBK
        Jan 23 '15 at 21:03















        5














        Not sure what you mean.



        mknod foo b 8 0


        Will create the device file called foo as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev that have the same type, major and minor, you can do (with zsh):





        • For block device 8:0:



          $ zmodload zsh/stat
          $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
          lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
          lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
          brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda



        • for char device 226:0:



          $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
          lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
          crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0



        Note that anything can create files in /dev. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc.



        On modern versions of Linux, it's usually udev based on input from the kernel.



        The name it chooses for the base device file is based on the DEVNAME supplied by the kernel. udev rules may change that but generally don't, and some udev rules will add some more symlinks for convenience (like the /dev/disk/by... ones).



        You can go from major:minor to kernel DEVNAME by looking at:



        $ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
        sda
        $ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
        dri/card0


        You can also get that information from the udev database as mikeserv has shown.






        share|improve this answer






























          5














          Not sure what you mean.



          mknod foo b 8 0


          Will create the device file called foo as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev that have the same type, major and minor, you can do (with zsh):





          • For block device 8:0:



            $ zmodload zsh/stat
            $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
            lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
            lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
            brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda



          • for char device 226:0:



            $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
            lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
            crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0



          Note that anything can create files in /dev. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc.



          On modern versions of Linux, it's usually udev based on input from the kernel.



          The name it chooses for the base device file is based on the DEVNAME supplied by the kernel. udev rules may change that but generally don't, and some udev rules will add some more symlinks for convenience (like the /dev/disk/by... ones).



          You can go from major:minor to kernel DEVNAME by looking at:



          $ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
          sda
          $ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
          dri/card0


          You can also get that information from the udev database as mikeserv has shown.






          share|improve this answer




























            5












            5








            5







            Not sure what you mean.



            mknod foo b 8 0


            Will create the device file called foo as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev that have the same type, major and minor, you can do (with zsh):





            • For block device 8:0:



              $ zmodload zsh/stat
              $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
              lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
              lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
              brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda



            • for char device 226:0:



              $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
              lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
              crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0



            Note that anything can create files in /dev. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc.



            On modern versions of Linux, it's usually udev based on input from the kernel.



            The name it chooses for the base device file is based on the DEVNAME supplied by the kernel. udev rules may change that but generally don't, and some udev rules will add some more symlinks for convenience (like the /dev/disk/by... ones).



            You can go from major:minor to kernel DEVNAME by looking at:



            $ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
            sda
            $ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
            dri/card0


            You can also get that information from the udev database as mikeserv has shown.






            share|improve this answer















            Not sure what you mean.



            mknod foo b 8 0


            Will create the device file called foo as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev that have the same type, major and minor, you can do (with zsh):





            • For block device 8:0:



              $ zmodload zsh/stat
              $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
              lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
              lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
              brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda



            • for char device 226:0:



              $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
              lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
              crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0



            Note that anything can create files in /dev. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc.



            On modern versions of Linux, it's usually udev based on input from the kernel.



            The name it chooses for the base device file is based on the DEVNAME supplied by the kernel. udev rules may change that but generally don't, and some udev rules will add some more symlinks for convenience (like the /dev/disk/by... ones).



            You can go from major:minor to kernel DEVNAME by looking at:



            $ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
            sda
            $ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
            dri/card0


            You can also get that information from the udev database as mikeserv has shown.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 23 '14 at 21:27

























            answered Aug 23 '14 at 21:18









            Stéphane ChazelasStéphane Chazelas

            310k57584945




            310k57584945























                5














                Apparently it can be done more simply with udevadm, and I've just found out how.



                To get the DEVNAME from udevadm you need only do:



                udevadm info -rq name $PATH


                For instance, if you wanted to know the /dev name for /sys/dev/char/5:1 you'd do:



                udevadm info -rq name /sys/dev/char/5:1


                OUTPUT



                /dev/console


                The -r option is to specify a --rooted path - without it the result above would read only console. The -q option specifies a database --query and it takes the operand name here - because we want the DEVNAME.



                A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:



                mmdev() for d in /sys/dev/[cb]*/$1:$2
                do [ -e "$d" ] || return
                printf %c:%s: "${d#/*/*/}" "${d##*/}"
                udevadm info -rq name "$d"
                done


                So running:



                mmdev 8 0


                prints...



                b:8:0:/dev/sda


                Here's the first one I wrote.



                majminpath() {
                set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
                udevadm info --export-db |
                sed 's|^[^=]*DEVNAME=||
                |^[^/]|!h;/MAJOR=/N
                |='"$1n.*=${2?}"'$|!d;g'
                }


                This just scans udevadm info --export-db output for the matching numbers. The output looks like:



                P: /devices/virtual/vc/vcsa4
                N: vcsa4
                E: DEVNAME=/dev/vcsa4
                E: DEVPATH=/devices/virtual/vc/vcsa4
                E: MAJOR=7
                E: MINOR=132
                E: SUBSYSTEM=vc

                P: /devices/virtual/vc/vcsa5
                N: vcsa5
                E: DEVNAME=/dev/vcsa5
                E: DEVPATH=/devices/virtual/vc/vcsa5
                E: MAJOR=7
                E: MINOR=133
                E: SUBSYSTEM=vc

                #...and so on


                The workflow is like:




                • attempt to strip the [^=]*DEVNAME= string from the head of each line


                • if a line does not have a first character or its first character is / copy that line over hold space


                • if a line matches MAJOR= append Next input line to pattern space


                • if there are 2 lines in pattern space that match =$1n.*=$2$ then copy hold space over pattern space and auto-print; else delete pattern space



                So if I do:



                majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1


                OUTPUT



                /dev/vcsa5
                /dev/sda
                /dev/sda1


                But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.






                share|improve this answer





















                • 1





                  Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                  – xae
                  Aug 23 '14 at 19:55











                • I gotta check subsystem - that's right. Thanks, @xae.

                  – mikeserv
                  Aug 23 '14 at 20:03
















                5














                Apparently it can be done more simply with udevadm, and I've just found out how.



                To get the DEVNAME from udevadm you need only do:



                udevadm info -rq name $PATH


                For instance, if you wanted to know the /dev name for /sys/dev/char/5:1 you'd do:



                udevadm info -rq name /sys/dev/char/5:1


                OUTPUT



                /dev/console


                The -r option is to specify a --rooted path - without it the result above would read only console. The -q option specifies a database --query and it takes the operand name here - because we want the DEVNAME.



                A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:



                mmdev() for d in /sys/dev/[cb]*/$1:$2
                do [ -e "$d" ] || return
                printf %c:%s: "${d#/*/*/}" "${d##*/}"
                udevadm info -rq name "$d"
                done


                So running:



                mmdev 8 0


                prints...



                b:8:0:/dev/sda


                Here's the first one I wrote.



                majminpath() {
                set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
                udevadm info --export-db |
                sed 's|^[^=]*DEVNAME=||
                |^[^/]|!h;/MAJOR=/N
                |='"$1n.*=${2?}"'$|!d;g'
                }


                This just scans udevadm info --export-db output for the matching numbers. The output looks like:



                P: /devices/virtual/vc/vcsa4
                N: vcsa4
                E: DEVNAME=/dev/vcsa4
                E: DEVPATH=/devices/virtual/vc/vcsa4
                E: MAJOR=7
                E: MINOR=132
                E: SUBSYSTEM=vc

                P: /devices/virtual/vc/vcsa5
                N: vcsa5
                E: DEVNAME=/dev/vcsa5
                E: DEVPATH=/devices/virtual/vc/vcsa5
                E: MAJOR=7
                E: MINOR=133
                E: SUBSYSTEM=vc

                #...and so on


                The workflow is like:




                • attempt to strip the [^=]*DEVNAME= string from the head of each line


                • if a line does not have a first character or its first character is / copy that line over hold space


                • if a line matches MAJOR= append Next input line to pattern space


                • if there are 2 lines in pattern space that match =$1n.*=$2$ then copy hold space over pattern space and auto-print; else delete pattern space



                So if I do:



                majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1


                OUTPUT



                /dev/vcsa5
                /dev/sda
                /dev/sda1


                But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.






                share|improve this answer





















                • 1





                  Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                  – xae
                  Aug 23 '14 at 19:55











                • I gotta check subsystem - that's right. Thanks, @xae.

                  – mikeserv
                  Aug 23 '14 at 20:03














                5












                5








                5







                Apparently it can be done more simply with udevadm, and I've just found out how.



                To get the DEVNAME from udevadm you need only do:



                udevadm info -rq name $PATH


                For instance, if you wanted to know the /dev name for /sys/dev/char/5:1 you'd do:



                udevadm info -rq name /sys/dev/char/5:1


                OUTPUT



                /dev/console


                The -r option is to specify a --rooted path - without it the result above would read only console. The -q option specifies a database --query and it takes the operand name here - because we want the DEVNAME.



                A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:



                mmdev() for d in /sys/dev/[cb]*/$1:$2
                do [ -e "$d" ] || return
                printf %c:%s: "${d#/*/*/}" "${d##*/}"
                udevadm info -rq name "$d"
                done


                So running:



                mmdev 8 0


                prints...



                b:8:0:/dev/sda


                Here's the first one I wrote.



                majminpath() {
                set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
                udevadm info --export-db |
                sed 's|^[^=]*DEVNAME=||
                |^[^/]|!h;/MAJOR=/N
                |='"$1n.*=${2?}"'$|!d;g'
                }


                This just scans udevadm info --export-db output for the matching numbers. The output looks like:



                P: /devices/virtual/vc/vcsa4
                N: vcsa4
                E: DEVNAME=/dev/vcsa4
                E: DEVPATH=/devices/virtual/vc/vcsa4
                E: MAJOR=7
                E: MINOR=132
                E: SUBSYSTEM=vc

                P: /devices/virtual/vc/vcsa5
                N: vcsa5
                E: DEVNAME=/dev/vcsa5
                E: DEVPATH=/devices/virtual/vc/vcsa5
                E: MAJOR=7
                E: MINOR=133
                E: SUBSYSTEM=vc

                #...and so on


                The workflow is like:




                • attempt to strip the [^=]*DEVNAME= string from the head of each line


                • if a line does not have a first character or its first character is / copy that line over hold space


                • if a line matches MAJOR= append Next input line to pattern space


                • if there are 2 lines in pattern space that match =$1n.*=$2$ then copy hold space over pattern space and auto-print; else delete pattern space



                So if I do:



                majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1


                OUTPUT



                /dev/vcsa5
                /dev/sda
                /dev/sda1


                But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.






                share|improve this answer















                Apparently it can be done more simply with udevadm, and I've just found out how.



                To get the DEVNAME from udevadm you need only do:



                udevadm info -rq name $PATH


                For instance, if you wanted to know the /dev name for /sys/dev/char/5:1 you'd do:



                udevadm info -rq name /sys/dev/char/5:1


                OUTPUT



                /dev/console


                The -r option is to specify a --rooted path - without it the result above would read only console. The -q option specifies a database --query and it takes the operand name here - because we want the DEVNAME.



                A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:



                mmdev() for d in /sys/dev/[cb]*/$1:$2
                do [ -e "$d" ] || return
                printf %c:%s: "${d#/*/*/}" "${d##*/}"
                udevadm info -rq name "$d"
                done


                So running:



                mmdev 8 0


                prints...



                b:8:0:/dev/sda


                Here's the first one I wrote.



                majminpath() {
                set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
                udevadm info --export-db |
                sed 's|^[^=]*DEVNAME=||
                |^[^/]|!h;/MAJOR=/N
                |='"$1n.*=${2?}"'$|!d;g'
                }


                This just scans udevadm info --export-db output for the matching numbers. The output looks like:



                P: /devices/virtual/vc/vcsa4
                N: vcsa4
                E: DEVNAME=/dev/vcsa4
                E: DEVPATH=/devices/virtual/vc/vcsa4
                E: MAJOR=7
                E: MINOR=132
                E: SUBSYSTEM=vc

                P: /devices/virtual/vc/vcsa5
                N: vcsa5
                E: DEVNAME=/dev/vcsa5
                E: DEVPATH=/devices/virtual/vc/vcsa5
                E: MAJOR=7
                E: MINOR=133
                E: SUBSYSTEM=vc

                #...and so on


                The workflow is like:




                • attempt to strip the [^=]*DEVNAME= string from the head of each line


                • if a line does not have a first character or its first character is / copy that line over hold space


                • if a line matches MAJOR= append Next input line to pattern space


                • if there are 2 lines in pattern space that match =$1n.*=$2$ then copy hold space over pattern space and auto-print; else delete pattern space



                So if I do:



                majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1


                OUTPUT



                /dev/vcsa5
                /dev/sda
                /dev/sda1


                But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Mar 11 '16 at 22:16









                ckujau

                1,209612




                1,209612










                answered Aug 23 '14 at 19:35









                mikeservmikeserv

                45.9k668161




                45.9k668161








                • 1





                  Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                  – xae
                  Aug 23 '14 at 19:55











                • I gotta check subsystem - that's right. Thanks, @xae.

                  – mikeserv
                  Aug 23 '14 at 20:03














                • 1





                  Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                  – xae
                  Aug 23 '14 at 19:55











                • I gotta check subsystem - that's right. Thanks, @xae.

                  – mikeserv
                  Aug 23 '14 at 20:03








                1




                1





                Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                – xae
                Aug 23 '14 at 19:55





                Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.

                – xae
                Aug 23 '14 at 19:55













                I gotta check subsystem - that's right. Thanks, @xae.

                – mikeserv
                Aug 23 '14 at 20:03





                I gotta check subsystem - that's right. Thanks, @xae.

                – mikeserv
                Aug 23 '14 at 20:03











                1














                Alas, the /sys/dev hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.



                Let $M and $m, respectively, be the major and minor number of our device file.




                Post 2.6.27 kernels



                As suggested by others, the simplest approach unleashes the power of the sysfs “virtual” file system, by chasing straight for files named $M:$m under the folder /sys/dev (more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent file (in a subshell so as to prevent namespace pollution):



                for file in $(find /sys/dev/ -name $M:$m)
                do
                (
                source ${file}/uevent
                echo $DEVNAME
                )
                done



                Pre 2.6.27 kernels



                Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m throughout the /sys/block hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev. If /sys/block/<...>/<DEV>/dev is one such file, then DEV is bound to be our device's name:



                dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"





                share|improve this answer




























                  1














                  Alas, the /sys/dev hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.



                  Let $M and $m, respectively, be the major and minor number of our device file.




                  Post 2.6.27 kernels



                  As suggested by others, the simplest approach unleashes the power of the sysfs “virtual” file system, by chasing straight for files named $M:$m under the folder /sys/dev (more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent file (in a subshell so as to prevent namespace pollution):



                  for file in $(find /sys/dev/ -name $M:$m)
                  do
                  (
                  source ${file}/uevent
                  echo $DEVNAME
                  )
                  done



                  Pre 2.6.27 kernels



                  Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m throughout the /sys/block hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev. If /sys/block/<...>/<DEV>/dev is one such file, then DEV is bound to be our device's name:



                  dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"





                  share|improve this answer


























                    1












                    1








                    1







                    Alas, the /sys/dev hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.



                    Let $M and $m, respectively, be the major and minor number of our device file.




                    Post 2.6.27 kernels



                    As suggested by others, the simplest approach unleashes the power of the sysfs “virtual” file system, by chasing straight for files named $M:$m under the folder /sys/dev (more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent file (in a subshell so as to prevent namespace pollution):



                    for file in $(find /sys/dev/ -name $M:$m)
                    do
                    (
                    source ${file}/uevent
                    echo $DEVNAME
                    )
                    done



                    Pre 2.6.27 kernels



                    Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m throughout the /sys/block hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev. If /sys/block/<...>/<DEV>/dev is one such file, then DEV is bound to be our device's name:



                    dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"





                    share|improve this answer













                    Alas, the /sys/dev hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.



                    Let $M and $m, respectively, be the major and minor number of our device file.




                    Post 2.6.27 kernels



                    As suggested by others, the simplest approach unleashes the power of the sysfs “virtual” file system, by chasing straight for files named $M:$m under the folder /sys/dev (more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent file (in a subshell so as to prevent namespace pollution):



                    for file in $(find /sys/dev/ -name $M:$m)
                    do
                    (
                    source ${file}/uevent
                    echo $DEVNAME
                    )
                    done



                    Pre 2.6.27 kernels



                    Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m throughout the /sys/block hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev. If /sys/block/<...>/<DEV>/dev is one such file, then DEV is bound to be our device's name:



                    dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Oct 16 '15 at 3:53









                    Roberto RealeRoberto Reale

                    1112




                    1112























                        0














                        On Linux it is possible to take advantage of certain files in /proc virtual filesystem.



                        $ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions 
                        8 1 29309568 sda1

                        $ grep '8:1[[:blank:]]' /proc/self/mountinfo
                        28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered


                        The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.






                        share|improve this answer




























                          0














                          On Linux it is possible to take advantage of certain files in /proc virtual filesystem.



                          $ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions 
                          8 1 29309568 sda1

                          $ grep '8:1[[:blank:]]' /proc/self/mountinfo
                          28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered


                          The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.






                          share|improve this answer


























                            0












                            0








                            0







                            On Linux it is possible to take advantage of certain files in /proc virtual filesystem.



                            $ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions 
                            8 1 29309568 sda1

                            $ grep '8:1[[:blank:]]' /proc/self/mountinfo
                            28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered


                            The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.






                            share|improve this answer













                            On Linux it is possible to take advantage of certain files in /proc virtual filesystem.



                            $ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions 
                            8 1 29309568 sda1

                            $ grep '8:1[[:blank:]]' /proc/self/mountinfo
                            28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered


                            The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Feb 25 at 22:36









                            Sergiy KolodyazhnyySergiy Kolodyazhnyy

                            10.6k42763




                            10.6k42763






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Unix & Linux Stack Exchange!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f151812%2fget-device-node-by-major-minor-numbers-pair%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                How to make a Squid Proxy server?

                                Is this a new Fibonacci Identity?

                                Touch on Surface Book