background

When working as A tool, you encountered the need to copy directory A to directory B.

The requirements are simple, but there are many possible scenarios:

  • Does directory A contain subdirectories
    • What if all you need to do is copy the files in A?
    • Are there files that need to be filtered out?
  • Check whether directory B already exists
  • .

For example, I ran into A problem when I did it. My directory A contained A hidden.git directory, and I forgot about it. I copied and overwrote.git from directory B, and then found that I changed the repository that A pointed to after committing git. This is embarrassing.

So it is important to analyze the file structure before doing so

Analyzing file structure

As mentioned, I have a.git directory in my directory that needs to be filtered out. Everything else is fine.

explore

Find which modules in Python can copy directories.

distutils.dir_util copy_tree

from distutils.dir_util import copy_tree
Copy the code

Python comes with it, and it’s easy to use,

copy_tree( src, dst[preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=0, dry_run=0]) every file in src is copied to dst, and directories under src are recursively copied to dst. Return the list of files that were copied or might have been copied, using their output name.

However, the specified directory or file cannot be filtered.

shutil

shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)

Recursively copy an entire directory tree rooted at src, returning the destination directory. The destination directory, named by dst, **must not already exist**; 
Copy the code

Analysis:

  • You can copy all files and subdirectories in directory A to B to meet requirements
  • There areignore pattern, can be filtered out.gitDirectory, meet the needs
  • But here’s the thing: the target pathdstMust not already exist, otherwise an error will be reported. Not meeting demand
    • However, Python 3.8 solves this problem and providesdirs_exist_ok=FalseParameters.
    • But MY local is still 3.7, and I don’t want to change to 3.8 yet
    • I have to delete B and then copy it

The sample code:

if os.path.exists(dst):
  shutil.rmtree(dst, ignore_errors=False)
  shutil.copytree(src, dst,ignore=shutil.ignore_patterns(".git"))
Copy the code

Write their own loop

For example, use os.walk or glob.glob

I won’t go into details. The advice is, don’t make wheels if you can. However, writing your own is highly recommended for beginners.