wisenhiemer
wisenhiemer

Reputation: 155

Unable to resolve path with os.walk

I have a bit of code that searches for files in a network share that match a certain keyword. When a match is found, I would like to copy the found files to a different location on the network. The error I'm getting is as follows:

Traceback (most recent call last):
File "C:/Users/user.name/PycharmProjects/SearchDirectory/Sub-Search.py", line 15, in <module>
shutil.copy(path+name, dest)
File "C:\Python27\lib\shutil.py", line 119, in copy
copyfile(src, dst)
File "C:\Python27\lib\shutil.py", line 82, in copyfile
with open(src, 'rb') as fsrc:
IOError: [Errno 2] No such file or directory: '//server/otheruser$/Document (user).docx'

I believe it's because I'm trying to copy the found file without specifying its direct path, since some of the files are found in subfolders. If so, how can I store the direct path to a file when it matches the keyword? Here is the code I have so far:

import os
import shutil


dest = '//dbserver/user.name$/Reports/User'
path = '//dbserver/User$/'

keyword = 'report'

print 'Starting'

for root, dirs, files in os.walk(path):
  for name in files:
      if keyword in name.lower():
         shutil.copy(path+name, dest)
         print name

print 'Done'

PS. The user folder being accessed is hidden, hence the $.

Upvotes: 1

Views: 1219

Answers (1)

Mad Physicist
Mad Physicist

Reputation: 114230

Looking at the docs for os.walk, your error is most likely that you are not including the full path. To avoid having to worry about things like trailing slashes and OS/specific path separators, you should also consider using os.path.join.

Replace path+name with os.path.join(root, name). The root element is the path of the subdirectory under path actually containing name, which you are currently omitting from your full path.

You should also replace dest with os.path.join(dest, os.path.relpath(root, path)) if you wish to preserve the directory structure in the destination. os.path.relpath subtracts the path prefix of path from root, allowing you to create the same relative path under dest. If the correct subfolders do not exist, you may want to call os.mkdir or better yet os.makedirs on them as you go:

for root, dirs, files in os.walk(path):
  out = os.path.join(dest, os.path.relpath(root, path))
  #os.makedirs(out) # You may end up with empty folders if you put this line here
  for name in files:
      if keyword in name.lower():
         os.makedirs(out) # This guarantees that only folders with at least one file get created
         shutil.copy(os.path.join(root, name), out)

Finally, look into shutil.copytree, wich does something very similar to what you want. The only disadvantage is that it does not offer the fine level of control for things like filtering that os.walk does (which you are using).

Upvotes: 3

Related Questions