Python: Get Mount Point on Windows or Linux
Windows didn't use to call them "mount points" [edit: it now does, see below!], and the two typical/traditional syntaxes you can find for them are either a drive letter, e.g. Z:
, or else \\hostname
(with two leading backslashes: escape carefully or use r'...'
notation in Python fpr such literal strings).
edit: since NTFS 5.0 mount points are supported, but according to this post the API for them is in quite a state -- "broken and ill-documented", the post's title says. Maybe executing the microsoft-supplied mountvol.exe is the least painful way -- mountvol drive:path /L
should emit the mounted volume name for the specified path, or just mountvol
such list all such mounts (I have to say "should" because I can't check right now). You can execute it with subprocess.Popen
and check its output.
How to find the mountpoint a file resides on?
You may either call the mount
command and parse its output to find the longest common prefix with your path, or use the stat
system call to get the device a file resides on and go up the tree until you get to a different device.
In Python, stat
may be used as follows (untested and may have to be extended to handle symlinks and exotic stuff like union mounts):
def find_mount_point(path):
path = os.path.abspath(path)
orig_dev = os.stat(path).st_dev
while path != '/':
dir = os.path.dirname(path)
if os.stat(dir).st_dev != orig_dev:
# we crossed the device border
break
path = dir
return path
Edit: I didn't know about os.path.ismount
until just now. This simplifies things greatly.
def find_mount_point(path):
path = os.path.abspath(path)
while not os.path.ismount(path):
path = os.path.dirname(path)
return path
Is it possible to get the mountpoint of a pendrive knowing its serialnumber using python?
To do that on Linux you will need to parse /proc/mounts
to determine mapping of device names to mountpoints, i.e. /dev/sdc2
-> /var/run/media/myaut/hyperx
.
The trick is to find out what device name has required serial number. Easiest approach to do so is to use udev
- it uses serial when generates symlinks in /dev/disk/by-id
:
/dev/disk/by-id/usb-Generic_Flash_Disk_12345678-0:0 -> ../../sdd
But we didn't seek for easiest solutions, are we? The trick is that udev
rules may be altered, and sysfs
(which come from kernel) is more reliable. I implemented a script that does that:
import os
import sys
import glob
SYS_USB_DEVICES = '/sys/bus/usb/devices'
SYS_BLOCK_DEVICES = '/sys/class/block'
try:
serial = sys.argv[1]
except IndexError:
print >> sys.stderr, "Usage: findflash.py SERIAL"
sys.exit(1)
# PASS 1 Find USB node with corresponding to serial
for usbid in os.listdir(SYS_USB_DEVICES):
usbserpath = os.path.join(SYS_USB_DEVICES, usbid, 'serial')
if not os.path.exists(usbserpath):
continue
with open(usbserpath) as f:
usb_serial = f.read().strip()
if serial == usb_serial:
# Found it!
break
else:
print >> sys.stderr, "Cannot find usb device with serial {0}".format(serial)
sys.exit(1)
# Find SCSI ids corresponding to this device
# I didn't check SYSFS documentation, but tested it on openSUSE 13.1
# The form of path is:
# <SUBDEVICE>/host<SCSI_HOST_ID>/target<SCSI_TARGET_ID>/<CTRL><CHANNEL>:<TGT>:<LUN>
# We need only basename
devs = glob.glob(os.path.join(SYS_USB_DEVICES, usbid,
'*/host*/target*/*:*:*:*'))
devs = map(os.path.basename, devs)
# PASS 2 - find mountpoints for devices with SCSI ids we discover earlier
# Parse mountpoint formatted as "/dev/... /path/to/mntpt ..."
def parse_mntpt(line):
dev, mntpt, _ = line.split(None, 2)
dev = os.path.basename(dev)
return dev, mntpt
mntpts = {}
with open('/proc/mounts') as f:
mntpts = dict(map(parse_mntpt, f.readlines()))
# List of ('scsi id', 'dev name', 'mnt pt (if exists)')
devlist = []
def create_dev(scsiid, devname):
global mntpts
devlist.append((scsiid, devname, mntpts.get(devname)))
for devname in os.listdir(SYS_BLOCK_DEVICES):
devpath = os.path.join(SYS_BLOCK_DEVICES, devname)
devlink = os.path.join(devpath, 'device')
# Node is "virtual", i.e. partition, ignore it
if not os.path.islink(devlink):
continue
scsiid = os.path.basename(os.readlink(devlink))
if scsiid not in devs:
continue
create_dev(scsiid, devname)
# Find partition names
parts = glob.glob(os.path.join(devpath, '*/partition'))
for partpath in parts:
partname = os.path.basename(os.path.dirname(partpath))
create_dev(scsiid, partname)
# END - print results
fmtstr = '{0:8} {1:5} {2}'
print fmtstr.format('SCSI ID', 'DEV', 'MOUNT POINT')
for scsiid, devname, mntpt in devlist:
print fmtstr.format(scsiid, devname, mntpt)
Here is example output:
$ python findflash.py 12345678
SCSI ID DEV MOUNT POINT
8:0:0:0 sdd None
8:0:0:0 sdd1 /var/run/media/myaut/Debian\040wheezy\04020140723-17:30
8:0:0:0 sdd2 None
8:0:0:0 sdd5 None
8:0:0:1 sr0 None
I can't say that on Windows that would be easy. I have a code (in C/WinAPI) that able to collect all disk devices from system, but it's logic is far away from filesystems representation, so I still didn't find a solution for that.
Complexity of Windows come from that:
- There is set of functions like SetupDi* that allow you enumerate disk devices. Their names are come in PnP style, unrelated to volume names.
- There is DOS-style API (i.e. working on level of A: and C:)
- There is WinNT-style API that knows about volumes, and probably, mountpoints.
Of course linking that three layers is not obvious (there is approach to match partitions by their size/offset, but that is crazy). I'm still scared to implement it in my library :(
Give the mount point of a path
df
takes the path as parameter, so something like this should be fairly robust;
df "$path" | tail -1 | awk '{ print $6 }'
Check if a directory is a mount point with python 2.7
There is an os.path.ismount(path)
.
Return True if pathname path is a mount point: a point in a file
system where a different file system has been mounted. The function
checks whether path‘s parent, path/.., is on a different device than
path, or whether path/.. and path point to the same i-node on the same
device — this should detect mount points for all Unix and POSIX
variants.
import os
os.path.ismount(dir_name) # returns boolean
You may also refer to implementation (if you're on POSIX system). Check macpath.py
or ntpath.py
for other platforms.
In Python, how can I get the file system of a given file path
Here is a slightly modified version of a recipe found here.os.path.realpath
was added so symlinks are handled correctly.
import os
def getmount(path):
path = os.path.realpath(os.path.abspath(path))
while path != os.path.sep:
if os.path.ismount(path):
return path
path = os.path.abspath(os.path.join(path, os.pardir))
return path
Related Topics
Pandas Read_SQL With Parameters
Do Not Want the Images to Load and CSS to Render on Firefox in Selenium Webdriver - Python
Linux:Python:Clear Input Buffer Before Raw_Input()
Python's Equivalent for R's Dput() Function
Oserror 38 [Errno 38] with Multiprocessing
Gunicorn Command Not Found, But It's in My Requirements.Txt
How to Install a Script to Run Anywhere from the Command Line
Extracting Data from HTML Table
Pyaudio Installation Error - 'Command 'Gcc' Failed with Exit Status 1'
How to Get Hard Disk Serial Number Using Python
Equivalent to Gettickcount() on Linux
How to Find the Mountpoint a File Resides On
What Is the Easiest Way to Detect Key Presses in Python 3 on a Linux MAChine
Python Convert Microsoft Office Docs to Plain Text on Linux
How to Pass a List Variable to Subprocess.Call Command in Python