Copy all files with a specific extension, keeping the directory tree

My problem :

  • Go to the directory and find all the header files *.h

    .
  • Copy all these files to a different location, but keep the directory tree

What I have tried :

I managed to collect all the headers using the library os

for root, dirs, files in os.walk(r'D:\folder\build'):
    for f in files:
        if f.endswith('.h'):
            print os.path.join(root, f)

      

This prints correctly:

D:\folder\build\a.h
D:\folder\build\b.h
D:\folder\build\subfolder\c.h
D:\folder\build\subfolder\d.h

      

Where I am stuck :

With a list of full file paths, how can I copy those files to a different location while preserving the subdirectories? In the above example, I would like to keep the directory structure below\build\

For example, I want a copy to create the following:

D:\other\subfolder\build\a.h
D:\other\subfolder\build\b.h
D:\other\subfolder\build\subfolder\c.h
D:\other\subfolder\build\subfolder\d.h

      

+4


source to share


3 answers


You can use shutil.copytree with the ignore option to filter files to copy.

"If the pointer is ignored, it must be a callable, which will take as its arguments the directory that copytree () visits and a list of its contents (...). The callable must return a sequence of directories and filenames relative to the current directory (that is . subset of elements in the second argument), then these names will be ignored during copying "



So, for your specific case, you can write:

from os.path import join, isfile
from shutil import copytree

# ignore any files but files with '.h' extension
ignore_func = lambda d, files: [f for f in files if isfile(join(d, f)) and f[-2:] != '.h']
copytree(src_dir, dest_dir, ignore=ignore_func)

      

+6


source


Edit: As @pchiquet shows, this can be done in one command. However, I will show you how you can manually fix this problem.

You will need three things.

You know which directory you were going through, so to create the destination path, you need to replace the source root name with the name of the destination root directory:

walked_directory = 'D:\folder\build'
found_file = 'D:\other\subfolder\build\a.h'
destination_directory = 'D:\other\subfolder'
destination_file = found_file.replace('walked_directory', 'destination_directory')

      



Now that you have a source and a destination, first you need to make sure the destination exists:

os.makedirs(os.path.dirname(destination_file))

      

Once it exists, you can copy the file:

shutil.copyfile(found_file, destination_file)

      

+2


source


This will recursively copy all files with the ".h" extension from the current directory to the dest_dir directory without creating subdirectories inside dest_dir:

import glob
import shutil
from pathlib import Path

# ignore any files but files with '.h' extension
for file in glob.glob('**/*.h', recursive=True):
    shutil.copyfile(
        Path(file).absolute(), 
        (Past(dest_dir)/Path(file).name).absolute()
    )

      

0


source







All Articles