Search code examples
pythoncopyshutilnon-recursive

How to perform a non recursive copy using python


I need to copy the files with certain patterns. I need to perform the non recursive copy on a given directory using shutil. I tried this code given below with performs recursive copy. Is there any options to specify in it to do the non recursive copy.

    from fnmatch import fnmatch, filter
    from os.path import isdir, join
    from shutil import copytree, ignore_patterns

    src_directory = r'PATH'
    dst_directory = r'PATH'
    copytree(src_directory, ignored_directory,ignore=ignore_patterns('*.txt'))

Solution

  • Make sure the destination directory exists first. Then create a list of all the files to ignore with glob.glob. Then iterate over all the file and directories in the src directory and copy each file to the dst directory if it is a file and it is not in the ignore list:

    import os, shutil, glob
    src = 'my_dir'
    dst = 'my_dir_cp'
    
    try:
        os.mkdir(dst)
    except FileExistsError:
        pass
    
    ignore = glob.glob(os.path.join(src, '*.txt'))
    for file in os.listdir(src):
        file = os.path.join(src, file)
        if file not in ignore and os.path.isfile(file):
            shutil.copy(file, dst)
    

    A full example:

    $ ls my_dir
    bob  cat.txt  fish  jim
    $ python -q
    >>> import os, shutil, glob
    >>> src = 'my_dir'
    >>> dst = 'my_dir_cp'
    >>> 
    >>> try:
    ...     os.mkdir(dst)
    ... except FileExistsError:
    ...     pass
    ... 
    >>> ignore = glob.glob(os.path.join(src, '*.txt'))
    >>> for file in os.listdir(src):
    ...     file = os.path.join(src, file)
    ...     if file not in ignore and os.path.isfile(file):
    ...         shutil.copy(file, dst)
    ... 
    'my_dir_cp/jim'
    'my_dir_cp/bob'
    >>> 
    $ ls my_dir_cp
    bob  jim
    

    If you want to be able to ignore multiple glob patterns, then you can glob.glob each of them and concatenate the results together (in a list-comprehension):

    import os, shutil, glob
    src = 'my_dir'
    dst = 'my_dir_cp'
    
    try:
        os.mkdir(dst)
    except FileExistsError:
        pass
    
    patterns_to_ignore = ['*.txt', '*.bat']
    ignore = [e for p in patterns_to_ignore for e in glob.glob(os.path.join(src, p))]
    for file in os.listdir(src):
        file = os.path.join(src, file)
        if file not in ignore and os.path.isfile(file):
            shutil.copy(file, dst)