3

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.

Community
  • 1
  • 1
GBh
  • 343
  • 1
  • 4
  • 15
  • It's `'\\\\?\\'`. You can't end a raw string on a single backslash, so you can't use a raw string for this. This is also a case where you can't substitute forward slashes, i.e. `'//?/'`. – Eryk Sun Jun 04 '14 at 20:16
  • hi eryksun it gave me this error when I ran it with '\\\\?\\' [Errno 22] invalid mode ('rb') or filename: , now I am sure the file name is correct and I have closed the file, I fail to understand why this is coming up – GBh Jun 04 '14 at 20:44
  • Is there any other way of handling long paths? I have big paths where the path string might go upto 1000 or 1500 characters – GBh Jun 05 '14 at 14:11
  • Hi eryksun this still gives me the same error, [Errno 2] No such file or directory, can we use python shell script to force copy of long paths? – GBh Jun 07 '14 at 19:55
  • My base path was an absolute path("C:\\test1234\\test4567\\...) and rest path was added in a loop to the base path using \\.join, and it still gives me the same error, the filesystem is NTFS. do you think python shell script can force the copy on long paths? is there a way to do this? – GBh Jun 07 '14 at 20:10
  • I Am using Microsoft Python Tools for visual studio, this what i get sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0) – GBh Jun 07 '14 at 20:12
  • Sorry about the tag, but it still gives me the same error when i use the unicode paths. do you think python shell script can force the copy on long paths? – GBh Jun 07 '14 at 20:24
  • Infact when i use the unicode path it gives me an IO Error 2 no such file or directory, and creates less number of folders than when not using unicode path. – GBh Jun 07 '14 at 20:46
  • Hey Eriksun it worked the issue was I was concatenation '\\\\?\\' this to my path using, so I instead I tried putting this directly before the path "\\\?\\c:\\tetst1234\\.." and it worked. Now I am wondering why it doesnt concatenate when we use "\\\\?\\" + "C:\\Teste1244\\.." – GBh Jun 07 '14 at 22:17

1 Answers1

4

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']
Eryk Sun
  • 33,190
  • 5
  • 92
  • 111