Home > Mobile >  How copy files recursively to another folder but without copying the source folder?
How copy files recursively to another folder but without copying the source folder?

Time:10-10

I have a script that copies files from one folder to another recursively depending on extensions and it works fine until Dst is in Src. Let me explain:

If I send .txt files to a subfolder that is in Src, the subfolder will copy itself. is there any way to prevent this from happening? I have tried with a break but it does not copy all the files because when the source_fn condition is met, the function stops. When source_fn == Dst is not met the script copies Dst back into itself. I know it sounds a bit confusing and I hope you can help me.

This is what Src looks like:

My documents
--- file.txt
--- folder (subfolder)
    --- file2.txt
--- Text_files (subfolder) Dst

This is how it currently works if I want the script to copy from Src (My Documents) only the .txt files to Dst (Text_Files) recursively maintaining the folder hierarchy:

My documents
--- file.txt
--- folder (subfolder)
    --- file2.txt
--- Text_files (subfolder) Dst
    ---file.txt
    ---Text_files (Subfolder)
       --- folder (subfolder)
           --- file2.txt
       ---file.txt
       --- folder (subfolder)
           --- file2.txt

As it should look:

My documents (Src)
---file.txt
--- Text_files (Subfolder) Dst
      ---file.txt
--- folder (subfolder)
    --- file2.txt

script:

import os
import winshell

def copywf1(Src, Dst, extensions)

        try:

            extensions = .txt .png

            for item in os.listdir(Src):
                source_fn = os.path.join(Src, item)

                if os.path.isdir(source_fn):
                    copywf1(source_fn, os.path.join(Dst, item), 
                    extensions, overwriten)

                elif os.path.splitext(item)[1] in extensions:

                    if not os.path.exists(Dst):
                        os.makedirs(Dst)

                        winshell.copy_file(source_fn, os.path.join(Dst, item), 
                        allow_undo=True, no_confirm=False, rename_on_collision=True, 
                        silent=False, hWnd=None)

        except winshell.x_winshell:
            pass

CodePudding user response:

You wrote

def copywf1(Src, Dst, extensions)
        try:
            extensions = .txt .png

Yeah, that's not going to work, is it?

Assign a set, rather than a syntax error:

            extensions = {'.txt', '.png'}

And use a shorter signature -- no point in asking the caller to pass it in if you're going to unconditionally overwrite it.

You can retrieve a given file's extension with

            root, ext = os.path.splitext(filepath)

and then ask

            if ext in extensions:

to conditionally copy desired file types.


Your code features a recursive call:

                if os.path.isdir(source_fn):
                    copywf1( ... )

Great, more power to you! If you can make it work. It isn't obvious to me that it does. I haven't puzzled out the path length invariant that it maintains. Also, your code passes 4 args but the signature accepts just 3.

Here is a simpler approach, using the standard os.walk() which recurses down the tree for you:

        for root, dirs, files in os.walk(Src):
            ...

spelling nit: pep-8 asks that you downcase it: src


When you get this working to your satisfaction, please do post the final code.

CodePudding user response:

If I send .txt files to a subfolder that is in Src, the subfolder will copy itself. Is there any way to prevent this from happening?

There is a way to resolve such kind of problems by thinking a bit "out of the box". Instead of searching for a way around the detected problem change the used method. For example by splitting the part searching for files which should be copied from the part actually copying them approaching it for example like this:

  • first collect paths to all the files you want to copy in a list

  • then loop over all elements of the list created before to actually copy the files

Splitting the task into this two steps helps to avoid potential problems with a destination folder within the folder tree from which files are copied. If there are already files in the destination folder and you haven't filtered them out in the first step you can in an intermediate step between the first and the second step remove from the list all of the files below the path to the destination folder.

Generally said: Avoid changes by deletion or addition of items in the structure (like a file system or a Python list or other kind of objects holding multiple items) you are traversing or going over in a loop or by recursion.

It will help you in the future to avoid this kind of problems like this one you just had run into.

  • Related