Search code examples
pythonusbfile-search

Python: How to search only USB flash drives?


I have a Python script which is designed to be run from a USB flash drive, and would not work if run from a PC hard drive, so it is safe to assume all copies exist on connected USBs.

I have another script designed to be run from the computer hard drive which seeks these USB scripts and configures them all in a certain way. Obviously to save time I do not want to search the entire hard drive when I know they are only on USBs. Is there a way to only search files on a connected USB, skipping searching local drives, through checking drive letters or the like?


Solution

  • Here's some example code to determine the drive type for every active logical drive on Windows, using ctypes...

    import ctypes
    
    # Drive types
    DRIVE_UNKNOWN     = 0  # The drive type cannot be determined.
    DRIVE_NO_ROOT_DIR = 1  # The root path is invalid; for example, there is no volume mounted at the specified path.
    DRIVE_REMOVABLE   = 2  # The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
    DRIVE_FIXED       = 3  # The drive has fixed media; for example, a hard disk drive or flash drive.
    DRIVE_REMOTE      = 4  # The drive is a remote (network) drive.
    DRIVE_CDROM       = 5  # The drive is a CD-ROM drive.
    DRIVE_RAMDISK     = 6  # The drive is a RAM disk.
    
    # Map drive types to strings
    DRIVE_TYPE_MAP = { DRIVE_UNKNOWN     : 'DRIVE_UNKNOWN',
                       DRIVE_NO_ROOT_DIR : 'DRIVE_NO_ROOT_DIR',
                       DRIVE_REMOVABLE   : 'DRIVE_REMOVABLE',
                       DRIVE_FIXED       : 'DRIVE_FIXED',
                       DRIVE_REMOTE      : 'DRIVE_REMOTE',
                       DRIVE_CDROM       : 'DRIVE_CDROM',
                       DRIVE_RAMDISK     : 'DRIVE_RAMDISK'}
    
    
    # Return list of tuples mapping drive letters to drive types
    def get_drive_info():
        result = []
        bitmask = ctypes.windll.kernel32.GetLogicalDrives()
        for i in range(26):
            bit = 2 ** i
            if bit & bitmask:
                drive_letter = '%s:' % chr(65 + i)
                drive_type = ctypes.windll.kernel32.GetDriveTypeA('%s\\' % drive_letter)
                result.append((drive_letter, drive_type))
        return result
    
    
    # Test
    if __name__ == '__main__':
        drive_info = get_drive_info()
        for drive_letter, drive_type in drive_info:
            print '%s = %s' % (drive_letter, DRIVE_TYPE_MAP[drive_type])
        removable_drives = [drive_letter for drive_letter, drive_type in drive_info if drive_type == DRIVE_REMOVABLE]
        print 'removable_drives = %r' % removable_drives
    

    ...which prints...

    C: = DRIVE_FIXED
    D: = DRIVE_FIXED
    E: = DRIVE_CDROM
    removable_drives = []
    

    ...before inserting a USB stick and...

    C: = DRIVE_FIXED
    D: = DRIVE_FIXED
    E: = DRIVE_CDROM
    F: = DRIVE_REMOVABLE
    removable_drives = ['F:']
    

    ...afterwards.

    Once you've got the list of removable drives, you can simply use os.walk() on each drive.