Copy a file with a too long path to another directory in Python

前端 未结 3 560
余生分开走
余生分开走 2020-12-14 10:20

I am trying to copy files on Windows with Python 2.7, but sometimes this fails.

shutil.copyfile(copy_file, dest_file)

I get the following I

相关标签:
3条回答
  • 2020-12-14 10:37

    Maybe do something like this:

    path = "some/really/really/long/path/more/than/255/chars.txt"
    
    def copyFile(path, dest, relative=0):
        if len(path) > 255:
            if not os.sep in path:
                raise SomeException()
            moveTo, path = path.split(os.sep, 1)
            os.chdir(moveTo)
            copyFile(path, dest, relative + 1)
        else:
            path_base = ['..'] * relative
            path_rel = path_base + [dest]
            shutil.copyfile(path, os.path.join(*path_rel))
    

    This is tested, and does work... however, if the destination is more than 255 chars, you would be back in the same boat. In that case, you may have to move the file several times.

    0 讨论(0)
  • 2020-12-14 10:53

    I wasn't sure about the 255 char limit so I stumbled on this post. There I found a working answer: adding \\?\ before the path.

    shutil.copyfile("\\\\?\\" + copy_file, dest_file)
    

    edit: I've found that working with long paths causes issues on Windows. Another trick I use is to just shorten the paths:

    import win32api
    path = win32api.GetShortPathName(path)
    
    0 讨论(0)
  • 2020-12-14 10:57

    Thanks for the answer Gfy. I have a requirement to use relative paths. The \\?\ can't be added successfully to a relative path, so it's necessary to convert to an absolute path first (run from desktop):

    import os
    
    def clean_path(path):
        path = path.replace('/',os.sep).replace('\\',os.sep)
        if os.sep == '\\' and '\\\\?\\' not in path:
            # fix for Windows 260 char limit
            relative_levels = len([directory for directory in path.split(os.sep) if directory == '..'])
            cwd = [directory for directory in os.getcwd().split(os.sep)] if ':' not in path else []
            path = '\\\\?\\' + os.sep.join(cwd[:len(cwd)-relative_levels]\
                             + [directory for directory in path.split(os.sep) if directory!=''][relative_levels:])
        return path
    
    clean_path('samples')
    \\?\C:\Users\Username\Desktop\samples
    clean_path('\samples')
    \\?\C:\Users\Username\Desktop\samples
    clean_path('..\samples')
    \\?\C:\Users\Username\samples
    clean_path('..\..\samples')
    \\?\C:\Users\samples
    clean_path('C:\Users\Username\Dropbox')
    \\?\C:\Users\Username\Dropbox
    
    0 讨论(0)
提交回复
热议问题