Copying specific files to a new folder, while maintaining the original subdirectory tree

前端 未结 1 985
忘掉有多难
忘掉有多难 2021-01-06 14:32

I have a large directory with many subdirectories that I am trying to sort, I am trying to copy specific file types to a new folder, but I want to maintain the original subd

相关标签:
1条回答
  • 2021-01-06 15:07

    You can do what you want with the built-in shutil.copytree() function by using (abusing?) its optional ignore keyword argument. The tricky part is that, if given, it must be a callable that returns what, in each directory, should not be copied, rather than what should be.

    However it possible to write a factory function similar to shutil.ignore_patterns() that creates a function that does what's needed, and use that as the ignore keyword argument's value.

    The function returned first determines what files to keep via the fnmatch.filter() function, then removes them from the list of everything which is in the given directory, unless they're a sub-directory name, in which case they're left in for later [recursive] processing. (This is what makes it copy the whole tree and what was probably wrong with your attempt to write your own copytree() function).

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # Works in Python 2.7 & 3.x
    
    import fnmatch
    from os.path import isdir, join
    
    def include_patterns(*patterns):
        """ Function that can be used as shutil.copytree() ignore parameter that
        determines which files *not* to ignore, the inverse of "normal" usage.
    
        This is a factory function that creates a function which can be used as a
        callable for copytree()'s ignore argument, *not* ignoring files that match
        any of the glob-style patterns provided.
    
        ‛patterns’ are a sequence of pattern strings used to identify the files to
        include when copying the directory tree.
    
        Example usage:
    
            copytree(src_directory, dst_directory,
                     ignore=include_patterns('*.sldasm', '*.sldprt'))
        """
        def _ignore_patterns(path, all_names):
            # Determine names which match one or more patterns (that shouldn't be
            # ignored).
            keep = (name for pattern in patterns
                            for name in fnmatch.filter(all_names, pattern))
            # Ignore file names which *didn't* match any of the patterns given that
            # aren't directory names.
            dir_names = (name for name in all_names if isdir(join(path, name)))
            return set(all_names) - set(keep) - set(dir_names)
    
        return _ignore_patterns
    
    
    if __name__ == '__main__':
    
        from shutil import copytree, rmtree
        import os
    
        src = r'C:\vols\Files\PythonLib\Stack Overflow'
        dst = r'C:\vols\Temp\temp\test'
    
        # Make sure the destination folder does not exist.
        if os.path.exists(dst) and os.path.isdir(dst):
            print('removing existing directory "{}"'.format(dst))
            rmtree(dst, ignore_errors=False)
    
        copytree(src, dst, ignore=include_patterns('*.png', '*.gif'))
    
        print('done')
    
    0 讨论(0)
提交回复
热议问题