Search code examples
pythonfilefile-move

How to move files from multiple specific subfolders in the same directory?


I'm trying to do the same as in this question: Copy files from multiple specific subfolders.

But none of the answers work for me at all. When I execute the py in my Windows cmd it doesn't even go into the loops, as I receive no print() line in the cmd window after executing.

I've tried this solution which copies the files from the directory but ignores all subfolders in that directory entirely.

I have tried looking into shutil but I don't think I can use it for my case because of the subfolders? It's really important that I don't keep the subfolder structure but just move all the files into one directory.

This is what I have right now but the output unfortunately keeps the folder structure:

import shutil
import os

# Define the source and destination path
source = "d:\\test"
destination = "d:\\test\SubfolderB"

# code to move the files from sub-folder to main folder.
files = os.listdir(source)
for file in files:
    file_name = os.path.join(source, file)
    shutil.move(file_name, destination)
print("Files Moved")

Solution

  • Issues 1 and 2:
    It appears that two of the primary issues in the original code is that os.listdir does not recurse into each sub-directory, but only provides a list of file and directory names, rather than the full path. So a two-fold issue here.

    To address this, the built-in glob library can be used. Per the documentation, a glob pattern of '**' along with the parameter recursive=True, will dive into each sub-directory and return the full file path, as desired.

    Note: If only a specific file type is required, the pattern can be changed to **/*.txt, or whatever file extension you're after.

    Issue 3:
    Additionally, the shutil.move command needs the full path to the destination, including the filename; which the original code does not address.

    Example code:

    import os
    import shutil
    from glob import glob
    
    # Path setup.
    path = './filemove'
    dest = './filemove_dest'
    
    # Collect files.
    files = glob(os.path.join(path, '**'), recursive=True)
    
    # Ensure destination path exists.
    if not os.path.isdir(dest):
        os.makedirs(dest)
    # Move all files.
    for f in files:
        if os.path.isfile(f):
            base = os.path.basename(f)
            shutil.move(f, os.path.join(dest, base))
    

    Original file structure:

    ./dir1
    ./dir1/dir1_file1
    ./dir1/dir1_file2
    ./dir1/dir1_file3
    ./dir1/dir1_file4
    ./dir1/dir1_file5
    ...
    ./dir5
    ./dir5/dir5_file1
    ./dir5/dir5_file2
    ./dir5/dir5_file3
    ./dir5/dir5_file4
    ./dir5/dir5_file5
    

    Results:

    ./filemove_dest/dir1_file1
    ./filemove_dest/dir1_file2
    ./filemove_dest/dir1_file3
    ...
    ./filemove_dest/dir5_file3
    ./filemove_dest/dir5_file4
    ./filemove_dest/dir5_file5