Is there a way to list all the available Windows' drives?

Viewed 64401
17 Answers

Without using any external libraries, if that matters to you:

import string
from ctypes import windll

def get_drives():
    drives = []
    bitmask = windll.kernel32.GetLogicalDrives()
    for letter in string.uppercase:
        if bitmask & 1:
            drives.append(letter)
        bitmask >>= 1

    return drives

if __name__ == '__main__':
    print get_drives()     # On my PC, this prints ['A', 'C', 'D', 'F', 'H']

Those look like better answers. Here's my hackish cruft

import os, re
re.findall(r"[A-Z]+:.*$",os.popen("mountvol /").read(),re.MULTILINE)

Riffing a bit on RichieHindle's answer; it's not really better, but you can get windows to do the work of coming up with actual letters of the alphabet

>>> import ctypes
>>> buff_size = ctypes.windll.kernel32.GetLogicalDriveStringsW(0,None)
>>> buff = ctypes.create_string_buffer(buff_size*2)
>>> ctypes.windll.kernel32.GetLogicalDriveStringsW(buff_size,buff)
8
>>> filter(None, buff.raw.decode('utf-16-le').split(u'\0'))
[u'C:\\', u'D:\\']

The Microsoft Script Repository includes this recipe which might help. I don't have a windows machine to test it, though, so I'm not sure if you want "Name", "System Name", "Volume Name", or maybe something else.

import win32com.client 
strComputer = "." 
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") 
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2") 
colItems = objSWbemServices.ExecQuery("Select * from Win32_LogicalDisk") 
for objItem in colItems: 
    print "Access: ", objItem.Access 
    print "Availability: ", objItem.Availability 
    print "Block Size: ", objItem.BlockSize 
    print "Caption: ", objItem.Caption 
    print "Compressed: ", objItem.Compressed 
    print "Config Manager Error Code: ", objItem.ConfigManagerErrorCode 
    print "Config Manager User Config: ", objItem.ConfigManagerUserConfig 
    print "Creation Class Name: ", objItem.CreationClassName 
    print "Description: ", objItem.Description 
    print "Device ID: ", objItem.DeviceID 
    print "Drive Type: ", objItem.DriveType 
    print "Error Cleared: ", objItem.ErrorCleared 
    print "Error Description: ", objItem.ErrorDescription 
    print "Error Methodology: ", objItem.ErrorMethodology 
    print "File System: ", objItem.FileSystem 
    print "Free Space: ", objItem.FreeSpace 
    print "Install Date: ", objItem.InstallDate 
    print "Last Error Code: ", objItem.LastErrorCode 
    print "Maximum Component Length: ", objItem.MaximumComponentLength 
    print "Media Type: ", objItem.MediaType 
    print "Name: ", objItem.Name 
    print "Number Of Blocks: ", objItem.NumberOfBlocks 
    print "PNP Device ID: ", objItem.PNPDeviceID 
    z = objItem.PowerManagementCapabilities 
    if z is None: 
        a = 1 
    else: 
        for x in z: 
            print "Power Management Capabilities: ", x 
    print "Power Management Supported: ", objItem.PowerManagementSupported 
    print "Provider Name: ", objItem.ProviderName 
    print "Purpose: ", objItem.Purpose 
    print "Quotas Disabled: ", objItem.QuotasDisabled 
    print "Quotas Incomplete: ", objItem.QuotasIncomplete 
    print "Quotas Rebuilding: ", objItem.QuotasRebuilding 
    print "Size: ", objItem.Size 
    print "Status: ", objItem.Status 
    print "Status Info: ", objItem.StatusInfo 
    print "Supports Disk Quotas: ", objItem.SupportsDiskQuotas 
    print "Supports File-Based Compression: ", objItem.SupportsFileBasedCompression 
    print "System Creation Class Name: ", objItem.SystemCreationClassName 
    print "System Name: ", objItem.SystemName 
    print "Volume Dirty: ", objItem.VolumeDirty 
    print "Volume Name: ", objItem.VolumeName 
    print "Volume Serial Number: ", objItem.VolumeSerialNumber 

Here is another great solution if you want to list only drives on your disc and not mapped network drives. If you want to filter by different attributes just print drps.

import psutil
drps = psutil.disk_partitions()
drives = [dp.device for dp in drps if dp.fstype == 'NTFS']

here's a simpler version, without installing any additional modules or any functions. Since drive letters can't go beyond A and Z, you can search if there is path available for each alphabet, like below:

>>> import os
>>> for drive_letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
        if os.path.exists(f'{drive_letter}:'):
            print(f'{drive_letter}:')
        else:
            pass

the one-liner:

>>> import os
>>> [f'{d}:' for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if os.path.exists(f'{d}:')]
['C:', 'D:']

This code will return of list of drivenames and letters, for example:

['Gateway(C:)', 'EOS_DIGITAL(L:)', 'Music Archive(O:)']

It only uses the standard library. It builds on a few ideas I found above. windll.kernel32.GetVolumeInformationW() returns 0 if the disk drive is empty, a CD rom without a disk for example. This code does not list these empty drives.

These 2 lines capture the letters of all of the drives:

bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1]  # strip off leading 0b and reverse
drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']

Here is the full routine:

from ctypes import windll, create_unicode_buffer, c_wchar_p, sizeof
from string import ascii_uppercase

def get_win_drive_names():
    volumeNameBuffer = create_unicode_buffer(1024)
    fileSystemNameBuffer = create_unicode_buffer(1024)
    serial_number = None
    max_component_length = None
    file_system_flags = None
    drive_names = []
    #  Get the drive letters, then use the letters to get the drive names
    bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1]  # strip off leading 0b and reverse
    drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']

    for d in drive_letters:
        rc = windll.kernel32.GetVolumeInformationW(c_wchar_p(d), volumeNameBuffer, sizeof(volumeNameBuffer),
                                                   serial_number, max_component_length, file_system_flags,
                                                   fileSystemNameBuffer, sizeof(fileSystemNameBuffer))
        if rc:
            drive_names.append(f'{volumeNameBuffer.value}({d[:2]})')  # disk_name(C:)
    return drive_names

This will help to find valid drives in windows os

import os
import string
drive = string.ascii_uppercase
valid_drives = []
for each_drive in drive:
    if os.path.exist(each_drive+":\\"):
       print(each_drive)
       valid_drives.append(each_drive+":\\")
print(valid_drives)

The output will be

C
D
E
['C:\\','D:\\','E:\\']

If you want only the letters for each drive, you can just:

from win32.win32api import GetLogicalDriveStrings


drives = [drive for drive in GetLogicalDriveStrings()[0]]
Related