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

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 [email protected], 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.

You could use lsblk:

lsblk -do name,tran
sda  sata
sdb  sata
sdd  usb

where -dor --nodeps means don't print slaves and -o name,tran or --output name,tran means list only name of device and device transport type. Add rm to the list of output columns to see which devices are removable (1 if true):

lsblk --nodeps --output NAME,TRAN,RM
sda  sata    0
sdb  sata    0
sdd  usb     1

I know a solution, but, sadly, it requires root privilege.  Anyway, you might still find it useful:

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 a USB device would be something like '[email protected]:2'.

Sample output:

       description: SATA controller
       physical id: d
       bus info: [email protected]:00:0d.0
       configuration: driver=ahci latency=64
          description: ATA Disk
          physical id: 0
          bus info: [email protected]:0.0.0
          logical name: /dev/sda
       physical id: 3
       bus info: [email protected]:2
       configuration: driver=usb-storage
          description: SCSI Disk
          physical id: 0.0.0
          bus info: [email protected]:0.0.0
          logical name: /dev/sdc