How to write a call back function for ignore in shutil.copytree
Asked Answered
J

4

8

I am relatively new to python. I am trying to copy a directory to another directory maintaining the structure.

I am using

    shutil.copytree(src, dst, symlinks=False, ignore=None, 
    copy_function=copy2, ignore_dangling_symlinks=False)

I am trying to write a call back function for ignore.

My aim is to take a list of files in a list , and copy only those files,ignoring the rest. How do we pass a list into the call back function?

I wrote a simple call back function , but I get some error when I try to run the copyTree function

   def abc(src,names):
    print(src)
    print(names)



    Traceback (most recent call last):
   File "<pyshell#23>", line 1, in <module>
shutil.copytree('D:\Mytest','D:\PythonTestDest3',symlinks=False,ignore=abc)
  File "C:\Python32\lib\shutil.py", line 204, in copytree
if name in ignored_names:
  TypeError: argument of type 'NoneType' is not iterable
Jeramie answered 10/8, 2011 at 14:43 Comment(0)
C
7

The return of the ignore function needs to be a list of directories and files to ignore. You aren't returning anything, which returns None, so you are getting the error TypeError: argument of type 'NoneType' is not iterable.

Here's an example that will copy the folder structure and the files listed in 'copy_these':

import os.path

copy_these = ['a.txt', 'b.txt', 'c.txt']

def ignore_most(folder, files):

    ignore_list = []
    for file in files:
       full_path = os.path.join(folder, file)
       if not os.path.isdir(full_path):
           if file not in copy_these:
               ignore_list.append(file)
    return ignore_list
Cogent answered 10/8, 2011 at 14:54 Comment(2)
You mean return [f for f in files if not is_dir(os.path.join(folder, f)) and f not in copy_these].Allenaallenby
Nice list comprehension. But, since the asker said he's new to Python, a more verbose style might be easier to understand and adapt.Cogent
F
6

The shutil module provides a ignore_patterns function.

This factory function creates a function that can be used as a callable for copytree()‘s ignore argument, ignoring files and directories that match one of the glob-style patterns provided.

The module page shows a couple of examples as well.

Fraudulent answered 10/8, 2011 at 14:49 Comment(1)
This works perfectly if you are try to ignore a file type (which is what I was looking for).Cavill
M
0

The ignore callback function should return a list of names relative to the 'src' directory that should not be copied.

Your example callback returns nothing (ie. None). Then copytree, expecting a list, tries to iterate over it. Since it can't, you get that exception.

Mapel answered 10/8, 2011 at 14:51 Comment(0)
A
0

If ignore is given, it must be a callable that will receive as its arguments the directory being visited ... and a list of its contents ... The callable must return a sequence of directory and file names relative to the current directory ...; these names will then be ignored in the copy process.

(docs)

My aim is to take a list of files in a list

Try an anonymous function (lambda) and a list comprehension:

copytree(src, dest,
         ignore=lambda d, files: [f for f in files
                                    if f not in files_to_copy
                                    and not is_dir(os.path.join(d, f))])

Note that the lambda function gets the basenames of the files and directories, not their full paths; kudos @jwhitlock's for the directory handling.

Allenaallenby answered 10/8, 2011 at 14:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.