Tell me more ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I know if /dev/sdX is a local HDD or usb key ? best doing this without root privileges.

OK , udevadm helped a lot:

For local HDD:

udevadm info --query=all --name=sdb | grep ID_BUS
E: ID_BUS=ata

For USB key:

udevadm info --query=all --name=sdc | grep ID_BUS
E: ID_BUS=usb
share|improve this question

5 Answers

up vote 5 down vote accepted

There are a few ways to tell without root privileges, many of them tricky/hacky:

Using /dev/disk/by-id:

find /dev/disk/by-id/ -lname '*sdX'

If this responds with something like /dev/disk/by-id/usb-blah-blah-blah, then it's a USB disk. Other prefixes include ata, dm, memstick, scsi, etc.

Using /dev/disk/by-path isn't significantly different:

find /dev/disk/by-path/ -lname '*sdX'

You'll get something like /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0. This shows the device path leading to the disk. In this case, a rough path is PCI → USB → disk. (note the -usb-).

Using udev (I run Debian. My udevadm is in /sbin which isn't on my $PATH — yours might be elsewhere, on or off your $PATH):

/sbin/udevadm info --query=all --name=sdX | grep ID_BUS

You'll get the bus type the device is on. Remove the | grep ID_BUS for the complete listing of information (you may need to add |less).

If you have lshw installed, Huygens' answer may also work:

lshw -class disk -class storage | less

And look through the output for your disk. In less, try / sdX and look at the preceding, bus info lines — the first one will just say scsi@…, but the one several lines before it will be more enlightening. However, you really should run this as the superuser so it may not be suitable. (symptoms: on the laptop I tried it, it listed the SATA disk but not the USB one — running with sudo listed both)

There are other ones too, more or less direct than these ones.

share|improve this answer

I know a solution, but it requires 'root' privilege sadly. Anyway, you might still found it usefull:

sudo lshw -class disk -class storage

For each device it will print the logical name (e.g. /dev/sda) and bus info which in case of USB device would be something like 'usb@1:2'.

Sample output:

[...]
  *-storage
       description: SATA controller
       physical id: d
       bus info: pci@0000:00:0d.0
       configuration: driver=ahci latency=64
[...]
     *-disk:0
          description: ATA Disk
          physical id: 0
          bus info: scsi@2:0.0.0
          logical name: /dev/sda
[...]
  *-scsi
       physical id: 3
       bus info: usb@1:2
       configuration: driver=usb-storage
     *-disk
          description: SCSI Disk
          physical id: 0.0.0
          bus info: scsi@6:0.0.0
          logical name: /dev/sdc
[...]
share|improve this answer

This doesn't need root privileges:

There are a quick way to ask about a sdX:

grep -H . /sys/block/sda/{capability,uevent,removable,device,{model,type,vendor,uevent}}
/sys/block/sda/capability:52
/sys/block/sda/uevent:MAJOR=8
/sys/block/sda/uevent:MINOR=0
/sys/block/sda/uevent:DEVNAME=sda
/sys/block/sda/uevent:DEVTYPE=disk
/sys/block/sda/removable:0
/sys/block/sda/device/model:WDC WD360GD-00FN
/sys/block/sda/device/type:0
/sys/block/sda/device/vendor:ATA     
/sys/block/sda/device/uevent:DEVTYPE=scsi_device
/sys/block/sda/device/uevent:DRIVER=sd
/sys/block/sda/device/uevent:MODALIAS=scsi:t-0x00

The realy interesting file is capability, On my Debian, I have a genhd.h file, so:

eval $(sed -ne '
   s/#define.*GENHD_FL_\([A-Z0-9_]*\)[ \t]*\([0-9]*\) \?.*$/GENHD_FLAGS[\2]="\1"/p
  ' /usr/src/linux-headers-2.6.32-5-common-openvz/include/linux/genhd.h)
diskCapa=$(</sys/block/sda/capability)
for i in ${!GENHD_FLAGS[@]};do
    [ $((diskCapa & i)) -ne 0 ] && echo ${GENHD_FLAGS[i]}
  done
MEDIA_CHANGE_NOTIFY
UP
SUPPRESS_PARTITION_INFO

diskCapa=$(</sys/block/sdd/capability)
    for i in ${!GENHD_FLAGS[@]};do
    [ $((diskCapa & i)) -ne 0 ] && echo ${GENHD_FLAGS[i]}
  done
REMOVABLE
MEDIA_CHANGE_NOTIFY
UP
SUPPRESS_PARTITION_INFO

At all, for only knowing if flag removable is set, ask for /sys/block/sdX/removable is a lot simplier! ;-)

So an USB key is removable, but as there are lot of removable device, I would prefer to ensure that size of medium is greater than 0.

My script:

I have 3 HD and 3 usb keys:

for dev in $( 
    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
  ) ;do
    echo "$dev \"$(
        sed -e 's/ *$//g' </sys/block/$dev/device/model
        )\""
  done

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

Nota: This is the very first part of a script I'm currently working on for installing a dual-boot live USB with ability of booting Debian or Ubuntu in persistent with a live-rw for Debian and a casper-rw for Ubuntu.

There is this very first part, which seem stable now and quiet, ( not as the rest of script with fdisk and mkfs).

#!/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...
share|improve this answer
Thanks to @StephaneChazelas for making the first part of my answer more readable. – F. Hauri Jan 5 at 19:34

I suggest just using hdparm or lshw (which you might need to install), and using sudo to execute it as root.

sudo hdparm -I /dev/sda
sudo lshw -short -C disk
sudo lshw -class disk -class storage

should all give you information.

share|improve this answer
hdparm on a virtual disk: hdparm -i /dev/sda /dev/sda: HDIO_DRIVE_CMD(identify) failed: Invalid exchange HDIO_GET_IDENTITY failed: Invalid argument – Tim Jun 6 '12 at 13:47
Well, I said should and it works here with virtual disks. – EightBitTony Jun 6 '12 at 13:52

After you plug in the USB device, run dmesg in a console window. You will be provided with some hints.

For example it will says something along the lines of "Device plugged in, mass storage /dev/sdd".

share|improve this answer
1  
Please provide more information/clarification to make your answer useful. – uther Jun 6 '12 at 13:20
How about not being insulting when answering a question? – Shadur Jun 8 '12 at 11:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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