how can the directory of a usb drive connected to a system be obtained?
Asked Answered
H

5

6

I need to obtain the path to the directory created for a usb drive(I think it's something like /media/user/xxxxx) for a simple usb mass storage device browser that I am making. Can anyone suggest the best/simplest way to do this? I am using an Ubuntu 13.10 machine and will be using it on a linux device.

Need this in python.

Hoang answered 24/3, 2014 at 16:57 Comment(3)
can think of anything other than parsing mount output. You can get device and path from this, see also #3881949Pennsylvania
@Pennsylvania could you put up a brief explanation/related question/link on how to do that ? I am both, a python and linux newbieHoang
I can't elaborate now or I get killed on spot by my gf... but I can answer you in few hours if you want.Pennsylvania
P
15

This should get you started:

#!/usr/bin/env python

import os
from glob import glob
from subprocess import check_output, CalledProcessError

def get_usb_devices():
    sdb_devices = map(os.path.realpath, glob('/sys/block/sd*'))
    usb_devices = (dev for dev in sdb_devices
        if 'usb' in dev.split('/')[5])
    return dict((os.path.basename(dev), dev) for dev in usb_devices)

def get_mount_points(devices=None):
    devices = devices or get_usb_devices() # if devices are None: get_usb_devices
    output = check_output(['mount']).splitlines()
    is_usb = lambda path: any(dev in path for dev in devices)
    usb_info = (line for line in output if is_usb(line.split()[0]))
    return [(info.split()[0], info.split()[2]) for info in usb_info]

if __name__ == '__main__':
    print get_mount_points()

How does it work?

First, we parse /sys/block for sd* files (courtesy of https://mcmap.net/q/591414/-find-which-drive-corresponds-to-which-usb-mass-storage-device-in-linux) to filter out usb devices. Later you call mount and parse output for lines only for those devices.

Of course they might be some edge cases, when this won't work, portability issues etc. Or better ways to do it. But for more information you should rather seek help on SuperUser or ServerFault, with more experienced linux hackers.

Pennsylvania answered 24/3, 2014 at 21:44 Comment(2)
Could you please explain the dict((os.path.split(dev)[-1], dev) part and devices = devices or get_usb_devices()?Hoang
the first returns dict, where keys are basename of devicepath and this path (bit of additional info that was useful to debug when writing this). devices = devices or get_usb_devices() is roughly the same as devices = devices if devices != None else get_usb_devices(), meaning that if there is no argument or it is None, it should call function go query devices. I hope it helps.Pennsylvania
A
6

I had to modify @m.wasowski 's code to make it work on Python3.5.4 as follows.

def get_mount_points(devices=None):
    devices = devices or get_usb_devices()  # if devices are None: get_usb_devices
    output = check_output(['mount']).splitlines()
    output = [tmp.decode('UTF-8') for tmp in output]

    def is_usb(path):
        return any(dev in path for dev in devices)
    usb_info = (line for line in output if is_usb(line.split()[0]))
    return [(info.split()[0], info.split()[2]) for info in usb_info]
Arraign answered 6/12, 2017 at 18:50 Comment(0)
H
4

Using m.wasowski code, unexpected behavior can occur:

return [(info.split()[0], info.split()[2]) for info in usb_info]

This part of code can produce bug, if your USB device name has white space character in it. I got that behavior with device named "USB DEVICE".

info.split()[2]

Returned media/home/USB for me, when it is media/home/USB DEVICE.

I modified that part, so it was founding word "type", and replaced that line with this:

#return [(info.split()[0], info.split()[2]) for info in usb_info]

fullInfo = []
for info in usb_info:
    print(info)
    mountURI = info.split()[0]
    usbURI = info.split()[2]
    print(info.split().__sizeof__())
    for x in range(3, info.split().__sizeof__()):
        if info.split()[x].__eq__("type"):
            for m in range(3, x):
                usbURI += " "+info.split()[m]
            break
    fullInfo.append([mountURI, usbURI])
return fullInfo
Hideaway answered 21/1, 2016 at 10:55 Comment(0)
L
0

I had to further modify @nick-sikrier and @m-wasowski response to handle LUKs encrypted devices.

def get_usb_devices():
    sdb_devices = map(os.path.realpath, glob('/sys/block/sd*'))
    usb_devices = (dev for dev in sdb_devices
                   if any(['usb' in dev.split('/')[5],
                           'usb' in dev.split('/')[6]]))
    return dict((os.path.basename(dev), dev) for dev in usb_devices)

def get_mount_points(
    devices = get_usb_devices()
    fullInfo = []
    for dev in devices:
        output = subprocess.check_output(['lsblk', '-lnpo', 'NAME,MOUNTPOINT', '/dev/' + dev]).splitlines()
    for mnt_point in output:
        mnt_point_split = mnt_point.split(' ', 1)
        if len(mnt_point_split) > 1 and mnt_point_split[1].strip():
            fullInfo.append([mnt_point_split[0], mnt_point_split[1]])
    return fullInfo
Lofty answered 21/9, 2020 at 21:25 Comment(1)
get_usb_devices() is returning an empty dict for me, even though ls /sys/block/ | grep "sd*" outputs sda and there's entries given by lsblk -lnpo NAME,MOUNTPOINT /dev/sda*Ferebee
A
0

With a simple shell pipe executed in python:

import subprocess
driver_name = "my_usb_stick"

path = subprocess.check_output("cat /proc/mounts | grep '"+driver_name+"' | awk '{print $2}'", shell=True)

path = path.decode('utf-8') # convert bytes in string
>>> "/media/user/my_usb_stick"

Explanations

  • /proc/mounts/ : Is a file listing all mounted devices
  • The 1st column specifies the device that is mounted.
  • The 2nd column reveals the mount point.
  • The 3rd column tells the file-system type.
  • The 4th column tells you if it is mounted read-only (ro) or read-write (rw).
  • The 5th and 6th columns are dummy values designed to match the format used in /etc/mtab

More details see this answer : How to interpret /proc/mounts?

  • grep returns the line containing your driver's name

  • awk returns the 2nd columns, aka the mount point, aka your path.

Allier answered 13/4, 2021 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.