Скопируйте файл со слишком длинным путем в другой каталог в 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
3 ответов
Я не был уверен в пределе 255 символов, поэтому я наткнулся на этот пост. Там я нашел рабочий ответ: добавление \\? перед тропой.
shutil.copyfile("\\?\" + copy_file, dest_file)
изменить: Я обнаружил, что работа с длинными путями вызывает проблемы в Windows. Еще один трюк, который я использую, - это просто сократить пути:
import win32api
path = win32api.GetShortPathName(path)
Спасибо за ответ Gfy. У меня есть требование использовать относительные пути. The \?\
не может быть успешно добавлен к относительному пути, поэтому сначала необходимо преобразовать в абсолютный путь (запустить с рабочего стола):
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
может сделать что-то вроде этого:
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 символов, вы вернетесь в ту же лодку. В этом случае вам, возможно, придется переместить файл несколько раз.