How to determine which sd* is usb?

71,829

Solution 1

Assuming you're on Linux.

Try:

sudo /lib/udev/scsi_id --page=0x80 --whitelisted --device=/dev/sdc

or:

cat /sys/block/sdc/device/{vendor,model}

You can also get information (including labels) from the filesystems on the different partitions with

sudo blkid /dev/sdc1

The pathid will help to determine the type of device:

readlink -f /sys/class/block/sdc/device

See also:

find /dev/disk -ls | grep /sdc

Which with a properly working udev would give you all the information from the other commands above.

The content of /proc/partitions will give you information on size (though not in as a friendly format as lsblk already mentionned by @Max).

sudo blockdev --getsize64 /dev/sdc

Will give you the size in bytes of the corresponding block device.

sudo smartctl -i /dev/sdc

(cross-platform), will also give you a lot of information including make, model, size, serial numbers, firmware revisions...

Solution 2

Finalized bash sample

There is a little part of a script I wrote to create and install live usb key, (dual boot ubuntu - debian):

The very first part USBKEYS=... is the answer to this question

In short, this:

list removable devices, driven by sd and having non zero size.

Note This script use dialog which seem not installed by default on Ubuntu. But dialog could be replaced by gdialog, whiptail or 'zenityor eveneasybashbui`.

#!/bin/bash

export USBKEYS=($(
    grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/ |
    xargs grep -Hv ^0$ |
    cut -d / -f 4
))

export STICK
case ${#USBKEYS[@]} in
    0 ) echo No USB Stick found; exit 0 ;;
    1 ) STICK=$USBKEYS ;;
    * )
    STICK=$(
    bash -c "$(
        echo -n  dialog --menu \
            \"Choose wich USB stick have to be installed\" 22 76 17;
        for dev in ${USBKEYS[@]} ;do
            echo -n \ $dev \"$(
                sed -e s/\ *$//g </sys/block/$dev/device/model
                )\" ;
            done
        )" 2>&1 >/dev/tty
    )
    ;;
esac

[ "$STICK" ] || exit 0

echo $STICK...

Sample (I've just connected 3 USB sticks -- in addition to my 3 hard disks):

dialog preview

Replacing dialog by gdialog (on line 24) give:

gdialog previw

But the syntax could be used with other dialog utility, like whiptail...

Essential part

export USBKEYS=($(
    grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/ |
    xargs grep -Hv ^0$ |
    cut -d / -f 4
))
for dev in ${USBKEYS[@]} ;do
    echo $dev \"$(
        sed -e s/\ *$//g </sys/block/$dev/device/model
        )\" ;
  done

sdd "Storage Media"
sde "Freecom Databar"
sdf "silicon-power"

Detailed explanation

This use some bashisms:

export USBKEYS=($(                         # Declaration of *array* 'USBKEYS'
    grep -Hv ^0$ /sys/block/*/removable |  # search for *not 0* in `removable` flag of all devices
    sed s/removable:.*$/device\\/uevent/ | # replace `removable` by `device/uevent` on each line of previous answer
    xargs grep -H ^DRIVER=sd |             # search for devices drived by `SD`
    sed s/device.uevent.*$/size/ |         # replace `device/uevent` by 'size'
    xargs grep -Hv ^0$ |                   # search for devices having NOT 0 size
    cut -d / -f 4                          # return only 4th part `/` separated
))
for dev in ${USBKEYS[@]} ;do               # for each devices in USBKEY...
    echo $dev \"$(r                        # echo device name and content of model file
        sed -e s/\ *$//g </sys/block/$dev/device/model
        )\" ;
  done

After having inserted three usb sticks on my desk:

grep -H . /sys/block/*/removable
/sys/block/loop0/removable:0
/sys/block/loop1/removable:0
...
/sys/block/sdc/removable:0
/sys/block/sdd/removable:1
/sys/block/sde/removable:1
/sys/block/sdf/removable:1
/sys/block/sr0/removable:1

(Yes my desk hold 3 physical hard drives: sda, sdb and sdc. First removable become sdd and sde).

So:

grep -Hv ^0$ /sys/block/*/removable
/sys/block/sdd/removable:1
/sys/block/sde/removable:1
/sys/block/sdf/removable:1
/sys/block/sr0/removable:1

I have the list of removable devices,

grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/
/sys/block/sdd/device/uevent
/sys/block/sde/device/uevent
/sys/block/sdf/device/uevent
/sys/block/sr0/device/uevent

 

grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd
/sys/block/sdd/device/uevent:DRIVER=sd
/sys/block/sde/device/uevent:DRIVER=sd
/sys/block/sdf/device/uevent:DRIVER=sd

I have the list of removable devices that driven by sd driver (i.e., not sr, nor floppy)

grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/
/sys/block/sdd/size
/sys/block/sde/size
/sys/block/sdf/size

 

grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/ |
    xargs grep -Hv ^0$
/sys/block/sdd/size:15224832
/sys/block/sde/size:7834944
/sys/block/sdf/size:7831552

 

grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/ |
    xargs grep -Hv ^0$ |
    cut -d / -f 4
sdd
sde
sdf

Also:

export USBKEYS=($(
    grep -Hv ^0$ /sys/block/*/removable |
    sed s/removable:.*$/device\\/uevent/ |
    xargs grep -H ^DRIVER=sd |
    sed s/device.uevent.*$/size/ |
    xargs grep -Hv ^0$ |
    cut -d / -f 4
))
set | grep ^USBKEYS=
USBKEYS=([0]="sdd" [1]="sde" [2]="sdf")

And finally:

cat /sys/block/$USBKEYS/device/model
Storage Media   

cat /sys/block/${USBKEYS[2]}/device/model
silicon-power   

but

printf "|%s|\n" "$(</sys/block/$USBKEYS/device/model)"
|Storage Media   |

It's because I wrote:

echo ${USBKEYS[2]} \"$(sed -e s/\ *$//g </sys/block/${USBKEYS[2]}/device/model)\"
sde "silicon-power"

Shrinked - golfed:

There is a shortened version

US=($(cut -d/ -f4 <(grep -vl ^0$ $(sed s@device/.*@size@ <(grep -l ^DRIVER=sd $(
    sed s+/rem.*$+/dev*/ue*+ <(grep -Hv ^0$ /sys/block/*/removable)) <(:))) <(:))))

(Nota: <(:) do pseudo empty file by fork to : this is shorter than /dev/null but not really equivalent)

Two lines and one variable UsbSticks holding:

set | grep ^US=
US=([0]="sde" [1]="sdf" [2]="sdg")

So the (begin of my) script could become:

#/bin/bash

US=($(cut -d/ -f4 <(grep -vl ^0$ $(sed s@device/.*@size@ <(grep -l ^DRIVER=sd $(
    sed s+/rem.*$+/dev*/ue*+ <(grep -Hv ^0$ /sys/block/*/removable)) <(:))) <(:))))
case ${#US[@]} in 0)echo "No USB stick found.";exit 0;;1)S=$US;;*)S=$(sh -c "$(
    sed -nre 's@/sys/block/(.*)/device/model:(.*)$@\1 "\2"@;H;${x;s/\n/ /g;
      s/^/whiptail --menu "Choose an USB stick" 22 76 14/;p}' <(grep -H . $(
     printf /sys/block/%s/device/model\\n ${US[@]})))" 2>&1 >/dev/tty) ;; esac
whiptail --defaultno --yesno "Could I destroy content of $S!?" 10 70 6 || exit 0

Solution 3

On recent version of Linux, there are /dev/disk/by-{id,label,path,uuid} directories that contain automagic symlinks to the various /dev/sdX and /dev/sdXN entries (I believe all of these are setup by udev). These provide more stable and informative names for your disks and partitions. I find /dev/disk/by-label/ the most useful (especially if you label your filesystem partitions), but by-path may be more useful for your use case.

Solution 4

udev knows your system. so you can get info through udevadm , under /sys/ like this (run as root, or with sudo depending on your distro)

udevadm info -a -p /sys/block/sdb

udevadm info -a -p /sys/block/sdc

reading through the output you'll come across some meaningful results, such as

ATTRS{vendor}
ATTRS{model}

you should be able to get some info about which one is the usb. additionally the variable

SUBSYSTEM=="usb"

should give you a nice big hint that we are talking about a usb.

then read the KERNEL variable to understand which sd* device is the usb.

Other commands that can be of help, are lshw that lists all your hardware by connection, lsusb which lists usb devices but doesn't show the sd* letter that has been provided. Also dmesg will give you all the necessary info if you type it just after you connect the usb to your computer.

These are all CLI commands, if your prefer something more GUI like some other lad will be able to help you more in that direction.

Solution 5

You can also use lsscsi command which prints various information about attached SCSI devices (obtained from /proc and /sys). You're interested in the transport info, so lsscsi -t | grep usb will tell you which device is using USB transport.

Share:
71,829

Related videos on Youtube

Benny Abramovici
Author by

Benny Abramovici

Developer who enjoys sharing knowledge. https://ksharma.dev Open source projects: Github

Updated on September 18, 2022

Comments

  • Benny Abramovici
    Benny Abramovici over 1 year

    Possible Duplicate:
    How to know if /dev/sdX is a connected USB or HDD?

    The output of ls /dev/sd* on my system is -

    sda  sda1  sda2  sda3  sda4  sda5  sda6  sda7  sdb  sdc  sdc1  sdc2
    

    How should I determine which drive is which?

    • TheMeaningfulEngineer
      TheMeaningfulEngineer over 11 years
      It is maybe worth mentioning that devices without numbers are discs (sda, sdb, sdc), and with numbers are partitions on that disc (sda1,sda2...,sdc1,sdc2).
    • atomAltera
      atomAltera over 11 years
      In debain I use df command, it displays me mounted devices (my debian mounts flash drives automatically when it plugged in) From which flash drive mounted to /media/usb. You can use mount command instant...
  • Izkata
    Izkata over 11 years
    Definitely the easiest. Just do ls -l /dev/disk/by-label/ or /by-path/ to get the entire mapping.
  • Jarek
    Jarek about 10 years
    I couldn't get this to work on Ubuntu 12.04. Could you add an explanation for how the bash code is supposed to work? Maybe then I can figure out why it isn't working for me. Thanks.
  • F. Hauri
    F. Hauri about 10 years
    Ok, I will post explanation. If you find what wrong, please let me know...
  • F. Hauri
    F. Hauri about 10 years
    @MountainX I've tested this under ubuntu 12-04 LTS just now, this worked fine!
  • F. Hauri
    F. Hauri about 10 years
    @MountainX Ok: on Ubuntu you have to replace dialog on line 24 by gdialog.
  • Jarek
    Jarek about 10 years
    @f-hauri - thanks! I will test it later today.
  • mikeserv
    mikeserv about 10 years
    lsblk -o tran,name,mountpoint would probably be a lot less work.
  • F. Hauri
    F. Hauri about 10 years
    @mikeserv Not sure! And in fine, your sample don't work.
  • F. Hauri
    F. Hauri about 10 years
    @mikeserv tran don't work in my Debian, and this don't tell if device is removable or not, if it is a cdrom (sata) or a card reader host... You're totaly wrong.
  • mikeserv
    mikeserv about 10 years
    Ok, probably it's older kernel - that's what Debian is known for. But surely, you can lsblk -o rm,name,mountpoint, yes? And besides, that should definitely trim the posssibilities from "who knows?" to two or three to stat in a for loop, yes?
  • mikeserv
    mikeserv about 10 years
    Just do lsblk --help. blockdev --help. findmnt --help. There's way more info in there than I'm gonna give you here.
  • F. Hauri
    F. Hauri about 10 years
    Thanks, I've already read all this stuff, but my previous answer stay: This don't give you a limited list of removable devices that not empty card reader... Or you have use this tools with strong syntax, and you have to grep or sed anyway. This stuf is recent (won't work under Debian 6, for sample) and work more or less in same way I manually do. At begin of my answer, I've explained that I use this already from some time.
  • mikeserv
    mikeserv about 10 years
    No, those are standard linux utils built around the standard libblkid Linux C library. These are tools built for this purpose by the people that maintain the kernel code that makes them work. They don't do what you manually do. And besides, I barely scratched the surface on the amount of information they can give you - just read the man pages.
  • mikeserv
    mikeserv about 10 years
    And you don't have to grep or sed anything - just read the --help and it will tell you how to simply pull your desired information in key=value pairs. For stat, lsblk, blkid, blockdev, findmnt, etc.
  • F. Hauri
    F. Hauri about 10 years
  • Jarek
    Jarek about 10 years
    @F.Hauri-could you fix the formatting of the last code block in your answer. And thanks for the great answer! (I'm hoping to get it to work for me.)
  • mikeserv
    mikeserv about 10 years
    It doesnt register as removable? Weird - Hauri and I worked it out together - that was one of the dependencies he set.
  • mikeserv
    mikeserv about 10 years
    At this point you'll just have to grep for the identifying keys you need. That's why I tried to provide it broken down in the other answer so you could see at what stage the available data was getting pared away.
  • qneill
    qneill over 8 years
    Thanks @cas, this helped me verify what I was seeing in dmesg. I was trying to fix a flash drive (marked as corrupted by Windows) using the camera+usb cable. It was not showing up in the device list; dmesg suggested '/dev/sde' but fdisk showed nothing. Using /dev/disk/by-id showed it, will have to remember this one.