Filter directory when using shutil.copytree?

Goles picture Goles · Oct 20, 2011 · Viewed 13.2k times · Source

Is there a way I can filter a directory by using the absolute path to it?

shutil.copytree(directory,
                target_dir,
                ignore = shutil.ignore_patterns("/Full/Path/To/aDir/Common")) 

This doesn't seem to work when trying to filter the "Common" Directory located under "aDir". If I do this:

shutil.copytree(directory,
                target_dir,
                ignore = shutil.ignore_patterns("Common"))

It works, but every directory called Common will be filtered in that "tree", which is not what I want.

Any suggestions ?

Thanks.

Answer

phihag picture phihag · Oct 20, 2011

You can make your own ignore function:

shutil.copytree('/Full/Path', 'target',
              ignore=lambda directory, contents: ['Common'] if directory == '/Full/Path/To/aDir' else [])

Or, if you want to be able to call copytree with a relative path:

import os.path
def ignorePath(path):
  def ignoref(directory, contents):
    return (f for f in contents if os.abspath(os.path.join(directory, f)) == path)
  return ignoref

shutil.copytree('Path', 'target', ignore=ignorePath('/Full/Path/To/aDir/Common'))

From the docs:

If ignore is given, it must be a callable that will receive as its arguments the directory being visited by copytree(), and a list of its contents, as returned by os.listdir(). Since copytree() is called recursively, the ignore callable will be called once for each directory that is copied. The callable must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process. ignore_patterns() can be used to create such a callable that ignores names based on glob-style patterns.