Search code examples
pythonfilerenamemoveshutil

Move all files from a directory tree to another directory. Rename if repeated names


I need to get all the files in a given directory tree (folder named Temp and subdirectories with more subdirectories and files...) encrypt them and move everything to a unique directory (folder named Temp2 with no subdirectories). If there are repeated names, I want to change name to, let's say, text.txt --> text(1).txt and continue moving that renamed file.

This is what I have at the moment:

bufferSize = 64 * 1024
password1 = 'password'

print('\n> Beginning recursive encryption...\n\n')
for archivo in glob.glob(sourcePath + '\\**\*', recursive=True):
   fullPath = os.path.join(sourcePath, archivo)
   fullNewf = os.path.join(destinationPath, archivo + '.aes')

   if os.path.isfile(fullPath):
      print('>>> Original: \t' + fullPath + '')
      print('>>> Encrypted: \t' + fullNewf + '\n')
      pyAesCrypt.encryptFile(fullPath, fullNewf, password1, bufferSize)
      shutil.move(fullPath + '.aes', destinationPath)

It encrypts just fine and proceeds to move encrypted files. The problem is that when it finds and tries to move a file with the an existing name, it gives me an error:

shutil.Error: Destination path 'E:\AAA\Folder\Folder\Temp2\Text.txt.aes' already exists

So I need to know how to rename files with repeated names in the proccess of moving them and then move them, but don't know how to proceed.


Solution

  • def make_unique_filename(file_path):
        duplicate_nr = 0
        base, extension = os.path.splitext(file_path)
        while os.path.exists(file_path):
            duplicate_nr += 1
            file_path = f'{base}({duplicate_nr}){extension}'
    
        return file_path
    

    and then

    os.rename(src_file_path, make_unique_filename(dest_file_path))
    

    shutil.move moves to a directory destination.

    It is easier to use os.rename. It moves a file to a new destination file. The new destination dir file should be unique, wihich you can do with make_unique_filename.

    This code is working for me now. There was another problem with your os.path.join. It is not necessary. glob.glob already returns a full path.

    import pyAesCrypt
    import os
    import glob
    
    sourcePath = r'E:\test aes\src'
    destinationPath = r'E:\test aes\dst'
    
    bufferSize = 64 * 1024
    password1 = 'password'
    
    def make_unique_filename(file_path):
        duplicate_nr = 0
        base, extension = os.path.splitext(file_path)
        while os.path.exists(file_path):
            duplicate_nr += 1
            file_path = f'{base}({duplicate_nr}){extension}'
    
       return file_path
    
    
    for archivo in glob.glob(sourcePath + '\\**\*', recursive=True):
        fullPath = archivo
        fullNewf = archivo + '.aes'
    
        if os.path.isfile(fullPath):
            print('>>> Original: \t' + fullPath + '')
            print('>>> Encrypted: \t' + fullNewf + '\n')
            pyAesCrypt.encryptFile(fullPath, fullNewf, password1, bufferSize)
    
            destination_file_path = os.path.join(destinationPath, os.path.split(fullNewf)[1])
            destination_file_path = make_unique_filename(destination_file_path)
            print(destination_file_path)
            os.rename(fullNewf, destination_file_path)