Copie arquivos usando python com estrutura de pasta completa

Nov 30 2020

Estou trocando meu SSD por um melhor em alguns dias e tenho muitos dados armazenados nele que posso me arrepender se forem excluídos. Os únicos tipos de arquivos de que preciso são arquivos PDF, arquivos docx, arquivos txt e outras coisas. Então, escrevi um script para localizar esses arquivos usando python.

# to copy all of my documents into another location.
import sys
import os
import time
import pathlib
import json


filePath=["D:\\", "C:\\Users"]
# ext=['mkv','docx','doc','pdf','mp4','zip',]
fileExt=["**\*.docx","**\*.doc","**\*.pdf"]
fileList={}
for each_drive in filePath:
    fileList[each_drive]={}
    for each_type in fileExt:
        fileList[each_drive][each_type]=list(pathlib.Path(each_drive).glob(each_type))

file1 = open('test.txt', 'w')
for each in fileList.values():
    for each2 in each.values():
        for entry in each2:
            print(entry)
            file1.writelines(str(str(entry)+ "\n"))


file1.close()

Esse script apenas localiza o arquivo com formatos que correspondem à lista FileExt e grava esses locais no arquivo test.txt. Agora preciso transferir esses arquivos, mantendo a estrutura de diretório exata. Por exemplo, se houver um arquivo como

C:\Users\<MyUser>\AppData\Local\Files\S0\1\Attachments\hpe[4].docx

O script deve copiar toda a estrutura do diretório como

<BackupDrive>:\<BackupFolderName>\C\Users\<MyUser>\AppData\Local\Files\S0\1\Attachments\hpe[4].docx

Como faço para copiar usando esta estrutura exata.
TLDR: preciso copiar os arquivos, mantendo a estrutura de diretórios como no Python
PS Estou usando o Windows, com Python 3.8

Respostas

FloLie Nov 29 2020 at 23:20

Para cada linha em sua lista de arquivos, faça o seguinte:

for filePath in fileList:
    destination = .join(['<BackupDrive>:\<BackupFolderName>', filePath[2:]])
    os.makedirs(os.path.dirname(filePath), exist_ok=True)
    shutil.copy(filePath , destination)
emmo Nov 29 2020 at 23:12

Como você pode gravar dados em um arquivo, presumo que também saiba ler os dados desse arquivo. Então, para cada linha (diga chamá-lo sourcenesse arquivo, use shutil.copyfile(source, dest).

Você pode criar a deststring manipulando source:

# remove 'C:'
str_split = source[2:]

# add backup drive and folder
dest = ''.join(['<BackupDrive>:\<BackupFolderName>', str_split])

Conforme mencionado nos comentários, o caminho de destino não será criado automaticamente, mas pode ser tratado como explicado aqui: crie o caminho de destino para arquivos shutil.copy

CrYbAbY Nov 29 2020 at 23:54

Agradecimentos a @Emmo e @FloLie por suas respostas. Eu apenas tive que usar a função os.makedirs () com o sinalizador exist_ok definido como true para cada arquivo na lista.

Este é o código colocado imediatamente após o código da pergunta.

#######################################
# create destination directory
file1=open ('test.txt', 'r')
text= file1.readlines()
# print(text)
for each in text:
    each=each[:-1]
    destination="BackupDIR-"+each[0]+each[2:]
    os.makedirs(os.path.dirname(destination), exist_ok=True)
    shutil.copy(each,destination)

Isso faz com que todo o código se pareça com:

# to copy all of my documents into another location.
import os
import time
import pathlib
import json
import shutil


filePath=["D:\\", "C:\\Users"]
# ext=['mkv','docx','doc','pdf','mp4','zip',]
fileExt=["**\*.docx","**\*.doc","**\*.pdf"]
fileList={}
for each_drive in filePath:
    fileList[each_drive]={}
    for each_type in fileExt:
        fileList[each_drive][each_type]=list(pathlib.Path(each_drive).glob(each_type))

file1 = open('test.txt', 'w')
for each in fileList.values():
    for each2 in each.values():
        for entry in each2:
            print(entry)
            file1.writelines(str(str(entry)+ "\n"))
file1.close()

#######################################
# create destination directory
file1=open ('test.txt', 'r')
text= file1.readlines()
# print(text)
for each in text:
    each=each[:-1]
    destination="BackupDIR-"+each[0]+each[2:]
    os.makedirs(os.path.dirname(destination), exist_ok=True)
    shutil.copy(each,destination)

PS Esta resposta está aqui apenas para pessoas como eu, que às vezes não conseguem entender pequenos fragmentos fora do contexto 😁