pythonshutilcopytree

Python shutil.ignore_patterns error


I'm trying to write a simple script to move files from one folder to another and filter unnecessary stuff out. I'm using the code below, but receiving an error

import shutil
import errno

def copy(src, dest):
    try:
        shutil.copytree(src, dest, ignore=shutil.ignore_patterns('*.mp4', '*.bak'))
    except OSError:
        if OSError.errno == errno.ENOTDIR:
            shutil.copy(src, dest)
        else:
             print("Directory not copied. Error: %s" % OSError)

src = raw_input("Please enter a source: ")
dest = raw_input("Please enter a destination: ")

copy(src, dest)

The error I get is:

Traceback (most recent call last):   
File "/Users/XXX/PycharmProjects/Folders/Fold.py", line 29,
  in <module>
  copy(src, dest)   
File "/Users/XXX/PycharmProjects/Folders/Fold.py", line 17,
  in copy
  ignore_pat = shutil.ignore_patterns('*.mp4', '*.bak') 
AttributeError: 'module' object has no attribute 'ignore_patterns'

Solution

  • Your Python version is too old. From the shutil.ignore_patterns() documentation:

    New in version 2.6.

    It is easy enough to replicate the method on older Python versions:

    import fnmatch 
    
    def ignore_patterns(*patterns):
        """Function that can be used as copytree() ignore parameter.
    
        Patterns is a sequence of glob-style patterns
        that are used to exclude files"""
        def _ignore_patterns(path, names):
            ignored_names = []
            for pattern in patterns:
                ignored_names.extend(fnmatch.filter(names, pattern))
            return set(ignored_names)
        return _ignore_patterns
    

    This'll work on Python 2.4 and newer.

    To simplify this down to your specific code:

    def copy(src, dest):
        def ignore(path, names):
            ignored = set()
            for name in names:
                if name.endswith('.mp4') or name.endswith('.bak'):
                    ignored.add(name)
            return ignored
    
        try:
            shutil.copytree(src, dest, ignore=ignore)
        except OSError:
            if OSError.errno == errno.ENOTDIR:
                shutil.copy(src, dest)
            else:
                 print("Directory not copied. Error: %s" % OSError)
    

    This doesn't use fnmatch at all anymore (since you are only testing for specific extensions) and uses syntax compatible with older Python versions.