Copy using the Windows copy dialog

后端 未结 4 2310
孤城傲影
孤城傲影 2021-02-14 23:47

I\'m currently using shutil.copy2() to copy a large number of image files and folders (anywhere between 0.5 and 5 gigs). Shutil works fine, but it\'s

相关标签:
4条回答
  • 2021-02-15 00:05

    If your goal is a fancy copy dialog, SHFileOperation Windows API function provides that. pywin32 package has a python binding for it, ctypes is also an option (google "SHFileOperation ctypes" for examples).

    Here is my (very lightly tested) example using pywin32:

    import os.path
    from win32com.shell import shell, shellcon
    
    
    def win32_shellcopy(src, dest):
        """
        Copy files and directories using Windows shell.
    
        :param src: Path or a list of paths to copy. Filename portion of a path
                    (but not directory portion) can contain wildcards ``*`` and
                    ``?``.
        :param dst: destination directory.
        :returns: ``True`` if the operation completed successfully,
                  ``False`` if it was aborted by user (completed partially).
        :raises: ``WindowsError`` if anything went wrong. Typically, when source
                 file was not found.
    
        .. seealso:
            `SHFileperation on MSDN <http://msdn.microsoft.com/en-us/library/windows/desktop/bb762164(v=vs.85).aspx>`
        """
        if isinstance(src, basestring):  # in Py3 replace basestring with str
            src = os.path.abspath(src)
        else:  # iterable
            src = '\0'.join(os.path.abspath(path) for path in src)
    
        result, aborted = shell.SHFileOperation((
            0,
            shellcon.FO_COPY,
            src,
            os.path.abspath(dest),
            shellcon.FOF_NOCONFIRMMKDIR,  # flags
            None,
            None))
    
        if not aborted and result != 0:
            # Note: raising a WindowsError with correct error code is quite
            # difficult due to SHFileOperation historical idiosyncrasies.
            # Therefore we simply pass a message.
            raise WindowsError('SHFileOperation failed: 0x%08x' % result)
    
        return not aborted
    

    You can also perform the same copy operation in "silent mode" (no dialog, no confirmationsm, no error popups) if you set the flags above to shellcon.FOF_SILENT | shellcon.FOF_NOCONFIRMATION | shellcon.FOF_NOERRORUI | shellcon.FOF_NOCONFIRMMKDIR. See SHFILEOPSTRUCT for details.

    0 讨论(0)
  • 2021-02-15 00:16

    Update: See

    • https://github.com/tjguk/winshell/
    • https://github.com/frmdstryr/pywinutils

    Would be nice to have it wrapped in a library... With the help of the answers above, I was able to get it working on windows 7 as follows.

    import pythoncom
    from win32com.shell import shell,shellcon
    
    def win_copy_files(src_files,dst_folder):           
            # @see IFileOperation
            pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation,None,pythoncom.CLSCTX_ALL,shell.IID_IFileOperation)
    
            # Respond with Yes to All for any dialog
            # @see http://msdn.microsoft.com/en-us/library/bb775799(v=vs.85).aspx
            pfo.SetOperationFlags(shellcon.FOF_NOCONFIRMATION)
    
            # Set the destionation folder
            dst = shell.SHCreateItemFromParsingName(dst_folder,None,shell.IID_IShellItem)
    
            for f in src_files:
                    src = shell.SHCreateItemFromParsingName(f,None,shell.IID_IShellItem)
                    pfo.CopyItem(src,dst) # Schedule an operation to be performed
    
    
            # @see http://msdn.microsoft.com/en-us/library/bb775780(v=vs.85).aspx
            success = pfo.PerformOperations()
    
            # @see sdn.microsoft.com/en-us/library/bb775769(v=vs.85).aspx
            aborted = pfo.GetAnyOperationsAborted()
            return success and not aborted
    
    
    files_to_copy = [r'C:\Users\jrm\Documents\test1.txt',r'C:\Users\jrm\Documents\test2.txt']
    dest_folder = r'C:\Users\jrm\Documents\dst'
    win_copy_files(files_to_copy,dest_folder)
    

    The references here were also very helpful: http://timgolden.me.uk/pywin32-docs/html/com/win32com/HTML/QuickStartClientCom.html

    0 讨论(0)
  • 2021-02-15 00:17

    *bump* Windows 10!

    With all your help and Virgil Dupras' send2trash:
    I just cooked a vanilla Python version only using ctypes:

    import os
    import ctypes
    from ctypes import wintypes
    
    
    class _SHFILEOPSTRUCTW(ctypes.Structure):
        _fields_ = [("hwnd", wintypes.HWND),
                    ("wFunc", wintypes.UINT),
                    ("pFrom", wintypes.LPCWSTR),
                    ("pTo", wintypes.LPCWSTR),
                    ("fFlags", ctypes.c_uint),
                    ("fAnyOperationsAborted", wintypes.BOOL),
                    ("hNameMappings", ctypes.c_uint),
                    ("lpszProgressTitle", wintypes.LPCWSTR)]
    
    
    def win_shell_copy(src, dst):
        """
        :param str src: Source path to copy from. Must exist!
        :param str dst: Destination path to copy to. Will be created on demand.
        :return: Success of the operation. False means is was aborted!
        :rtype: bool
        """
        if not os.path.exist(src):
            print('No such source "%s"' % src)
            return False
    
        src_buffer = ctypes.create_unicode_buffer(src, len(src) + 2)
        dst_buffer = ctypes.create_unicode_buffer(dst, len(dst) + 2)
    
        fileop = _SHFILEOPSTRUCTW()
        fileop.hwnd = 0
        fileop.wFunc = 2  # FO_COPY
        fileop.pFrom = wintypes.LPCWSTR(ctypes.addressof(src_buffer))
        fileop.pTo = wintypes.LPCWSTR(ctypes.addressof(dst_buffer))
        fileop.fFlags = 512  # FOF_NOCONFIRMMKDIR
        fileop.fAnyOperationsAborted = 0
        fileop.hNameMappings = 0
        fileop.lpszProgressTitle = None
    
        result = ctypes.windll.shell32.SHFileOperationW(ctypes.byref(fileop))
        return not result
    

    ✔ Tested on Python 3.7 and 2.7 also with long src and dst paths.

    0 讨论(0)
  • 2021-02-15 00:23

    See IFileCopy. IFileOperation may be available through ctypes and shell32.dll, I am not sure.

    0 讨论(0)
提交回复
热议问题