Подтвердить что ты не робот

Скопируйте файл с слишком длинным путем в другой каталог в Python

Я пытаюсь скопировать файлы в Windows с помощью Python 2.7, но иногда это терпит неудачу.

shutil.copyfile(copy_file, dest_file)

Я получаю следующее IOError:

[Errno 2] No such file or directory

Но файл существует! Проблема в том, что путь к файлу слишком длинный. ( > 255 символов)

Как скопировать эти файлы? Не открывать их в других приложениях.

Чтобы создать файл со слишком длинным путем, создайте файл с максимально возможным именем файла и переместите содержащую папку глубже по древовидной структуре.

Я пробовал некоторые из этих методов без успеха: http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

4b9b3361

Ответ 1

Я не был уверен в предел 255 char, поэтому я наткнулся на этот пост. Там я нашел рабочий ответ: добавив \\?\До пути.

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

изменить: Я обнаружил, что работа с длинными путями вызывает проблемы в Windows. Еще один трюк, который я использую, - это просто сократить пути:

import win32api
path = win32api.GetShortPathName(path)

Ответ 2

Спасибо за ответ Gfy. У меня есть требование использовать относительные пути. \\?\ нельзя добавить к относительному пути, поэтому сначала необходимо преобразовать в абсолютный путь (запустить с рабочего стола):

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

Ответ 3

Может быть, что-то вроде этого:

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))

Это проверено и работает... однако, если место назначения составляет более 255 символов, вы вернетесь в одну лодку. В этом случае вам может потребоваться переместить файл несколько раз.