it-swarm.it

Python: sposta e sovrascrive file e cartelle

Ho una directory, 'Dst Directory', che contiene file e cartelle e ho 'src Directory' che contiene anche file e cartelle. Quello che voglio fare è spostare il contenuto di 'src Directory' in 'Dst Directory' e sovrascrivere anyfiles che esistono con lo stesso nome. Ad esempio, "Src Directory\file.txt" deve essere spostato in "Directory Dst" e sovrascrivere il file.txt esistente. Lo stesso vale per alcune cartelle, lo spostamento di una cartella e l'unione dei contenuti con la stessa cartella in "directory dst"

Attualmente sto usando shutil.move per spostare il contenuto di src in dst ma non lo farà se i file esistono già e non unirà le cartelle; metterà semplicemente la cartella all'interno della cartella esistente.

Aggiornamento: per rendere le cose un po 'più chiare; Quello che sto facendo è decomprimere un archivio nella directory di Dst e quindi spostare i contenuti della directory Src e fare il rezipping, aggiornando efficacemente i file nell'archivio Zip. Questo verrà ripetuto per l'aggiunta di nuovi file o nuove versioni di file ecc. Ecco perché è necessario sovrascrivere e unire

Risolto: ho risolto il mio problema utilizzando distutils.dir_util.copy_tree (src, dst), questo copia le cartelle ei file dalla directory src alla directory dst e sovrascrive/unisce dove necessario. Spero che aiuti alcune persone!

Spero che abbia senso, Grazie!

59
Artharos

Utilizzare invece copy(), che è disposto a sovrascrivere i file di destinazione. Se poi vuoi che il primo albero vada via, solo rmtree() lo fa separatamente una volta che hai finito di iterarlo.

http://docs.python.org/library/shutil.html#shutil.copy

http://docs.python.org/library/shutil.html#shutil.rmtree

Aggiornare:

Fai un os.walk() sull'albero dei sorgenti. Per ogni directory, controlla se esiste sul lato di destinazione e os.makedirs() se manca. Per ogni file, semplicemente shutil.copy() e il file verrà creato o sovrascritto, a seconda del caso.

41
Brandon Rhodes

Passerà attraverso la directory di origine, creerà qualsiasi directory che non esiste già nella directory di destinazione e trasferirà i file dall'origine alla directory di destinazione:

import os
import shutil

root_src_dir = 'Src Directory\\'
root_dst_dir = 'Dst Directory\\'

for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            # in case of the src and dst are the same file
            if os.path.samefile(src_file, dst_file):
                continue
            os.remove(dst_file)
        shutil.move(src_file, dst_dir)

Tutti i file preesistenti verranno rimossi per primi (tramite os.remove) prima di essere sostituiti dal file sorgente corrispondente. Tutti i file o le directory che esistono già nella destinazione ma non nella sorgente rimarranno intatti.

50
Ray Vega

Poiché nessuno dei precedenti ha funzionato per me, ho scritto la mia funzione ricorsiva. Chiama Funzione copyTree (dir1, dir2) per unire le directory. Esegui su più piattaforme Linux e Windows. 

def forceMergeFlatDir(srcDir, dstDir):
    if not os.path.exists(dstDir):
        os.makedirs(dstDir)
    for item in os.listdir(srcDir):
        srcFile = os.path.join(srcDir, item)
        dstFile = os.path.join(dstDir, item)
        forceCopyFile(srcFile, dstFile)

def forceCopyFile (sfile, dfile):
    if os.path.isfile(sfile):
        shutil.copy2(sfile, dfile)

def isAFlatDir(sDir):
    for item in os.listdir(sDir):
        sItem = os.path.join(sDir, item)
        if os.path.isdir(sItem):
            return False
    return True


def copyTree(src, dst):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isfile(s):
            if not os.path.exists(dst):
                os.makedirs(dst)
            forceCopyFile(s,d)
        if os.path.isdir(s):
            isRecursive = not isAFlatDir(s)
            if isRecursive:
                copyTree(s, d)
            else:
                forceMergeFlatDir(s, d)
6
ALLOY

Se devi anche sovrascrivere i file con flag di sola lettura, usa questo:

def copyDirTree(root_src_dir,root_dst_dir):
"""
Copy directory tree. Overwrites also read only files.
:param root_src_dir: source directory
:param root_dst_dir:  destination directory
"""
for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            try:
                os.remove(dst_file)
            except PermissionError as exc:
                os.chmod(dst_file, stat.S_IWUSR)
                os.remove(dst_file)

        shutil.copy(src_file, dst_dir)
3
Vit Bernatik

Dai un'occhiata a: os.remove per rimuovere i file esistenti.

1
phimuemue

Ho avuto un problema simile. Volevo spostare i file e le strutture delle cartelle e sovrascrivere i file esistenti, ma non eliminare nulla che si trova nella struttura della cartella di destinazione.

L'ho risolto usando os.walk(), chiamando ricorsivamente la mia funzione e utilizzando shutil.move() su file che volevo sovrascrivere e cartelle che non esistevano.

Funziona come shutil.move(), ma con il vantaggio che i file esistenti vengono solo sovrascritti, ma non cancellati.

import os
import shutil

def moverecursively(source_folder, destination_folder):
    basename = os.path.basename(source_folder)
    dest_dir = os.path.join(destination_folder, basename)
    if not os.path.exists(dest_dir):
        shutil.move(source_folder, destination_folder)
    else:
        dst_path = os.path.join(destination_folder, basename)
        for root, dirs, files in os.walk(source_folder):
            for item in files:
                src_path = os.path.join(root, item)
                if os.path.exists(dst_file):
                    os.remove(dst_file)
                shutil.move(src_path, dst_path)
            for item in dirs:
                src_path = os.path.join(root, item)
                moverecursively(src_path, dst_path)
0
the