-->

Python: copy long file path Shutil.copyfile

2020-03-30 03:54发布

问题:

I want to copy too long paths with python using shutil.copyfile.

Now I read this Copy a file with a too long path to another directory in Python page to get the solution. I used:

    shutil.copyfile(r'\\\\?\\' +  ErrFileName,testPath+"\\"+FilenameforCSV+"_lyrErrs"+timestrLyr+".csv")

to copy the file but it gives me an error : [Errno 2] No such file or directory: '\\\\?\\C:\\...

Can anyone please let me know how to incorporate longs paths with Shutil.copyfile, the method I used above should allow 32k characters inside a file path, but I cant even reach 1000 and it gives me this error.

回答1:

Since the \\?\ prefix bypasses normal path processing, the path needs to be absolute, can only use backslash as the path separator, and has to be a UTF-16 string. In Python 2, use the u prefix to create a unicode string (UTF-16 on Windows).

shutil.copyfile opens the source file in 'rb' mode and destination file in 'wb' mode, and then copies from source to destination in 16 KiB chunks. Given a unicode path, Python 2 opens a file by calling the C runtime function _wfopen, which in turn calls the Windows wide-character API CreateFileW.

shutil.copyfile should work with long paths, assuming they're correctly formatted. If it's not working for you, I can't think of any way to "force" it to work.

Here's a Python 2 example that creates a 10-level tree of directories, each named u'a' * 255, and copies a file from the working directory into the leaf of the tree. The destination path is about 2600 characters, depending on your working directory.

#!python2
import os
import shutil

work = 'longpath_work'
if not os.path.exists(work):
    os.mkdir(work)
os.chdir(work)

# create a text file to copy
if not os.path.exists('spam.txt'):
    with open('spam.txt', 'w') as f:
        f.write('spam spam spam')

# create 10-level tree of directories
name = u'a' * 255
base = u'\\'.join([u'\\\\?', os.getcwd(), name])
if os.path.exists(base):
    shutil.rmtree(base)
rest = u'\\'.join([name] * 9)
path = u'\\'.join([base, rest])
os.makedirs(path)

print 'src directory listing (tree created)'
print os.listdir(u'.')

dest = u'\\'.join([path, u'spam.txt'])
shutil.copyfile(u'spam.txt', dest)
print '\ndest directory listing'
print os.listdir(path)

print '\ncopied file contents'
with open(dest) as f:
    print f.read()

# Remove the tree, and verify that it's removed:
shutil.rmtree(base)
print '\nsrc directory listing (tree removed)'
print os.listdir(u'.')

Output (line wrapped):

src directory listing (tree created)
[u'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
   aaaaa', u'spam.txt']

dest directory listing
[u'spam.txt']

copied file contents
spam spam spam

src directory listing (tree removed)
[u'spam.txt']