2011-09-14 39 views
51

Ho una directory, 'Directory Dst', 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 la fusione dei contenuti con la stessa cartella in "directory dst"Python - Spostamento e sovrascrittura di file e cartelle

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 di Src Directory lì e fare il rezipping, aggiornando efficacemente i file nell'archivio zip. Questo sarà 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 e file dalla directory src alla directory dst e sovrascrive/unisce dove necessario. Spero che aiuti alcune persone!

Spero che abbia senso, grazie!

+0

Si noti che [ 'distutils.dir_util.copy_tree'] (https://docs.python.org/dev /distutils/apiref.html#distutils.dir_util.copy_tree) non è in grado di copiare file speciali, ad es. [named pipes] (https://en.wikipedia.org/wiki/Named_pipe) (genera 'distutils.errors.DistutilsFileError'). –

risposta

35

Utilizzare invece copy(), che è disposto a sovrascrivere i file di destinazione. Se poi vuoi che il primo albero vada via, solo rmtree() 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

Aggiornamento:

fare un os.walk() sopra la struttura di origine. Per ogni directory, controllare 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.

+0

copy() can ' Tuttavia, è possibile copiare le cartelle? – Artharos

+0

No, ma 'move()' su ogni file inoltre non crea le directory di destinazione, quindi ho assunto che il tuo codice abbia già fatto un 'os.makedirs()' nelle cartelle di destinazione che non esistevano. Ah! Penso di capire adesso - stavi facendo 'move()' sull'albero * whole * in una volta? Gotchya. Aggiornerà la mia risposta –

+0

Grazie per l'aggiornamento, il problema è che i file da copiare cambiano sempre (nuovi file aggiunti, ecc.) Quindi dovrei aggiornare il codice ogni volta che ho aggiunto nuovi file per lo spostamento, se lo capisci. Comunque, l'ho gestito con distutils.dir_util.copy_tree (src, dst) che copia le cartelle e i file e sovrascrive/unisce dove necessario, grazie per l'aiuto – Artharos

1

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

+0

Il problema è che i file che voglio aggiungere alla cartella cambieranno (ne verranno aggiunti di nuovi e quelli vecchi aggiornati) quindi non posso avere un elenco di elementi da rimuovere, grazie anche a – Artharos

44

Questo passerà attraverso la directory di origine, creare tutte le directory che non sono già presenti nella directory di destinazione, e spostare i file dalla sorgente 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): 
      os.remove(dst_file) 
     shutil.move(src_file, dst_dir) 

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

+3

Che bello, grazie! Penso che sia quello di cui parlava Brandon Craig Rhodes, ma grazie per aver fornito un frammento! Purtroppo non è possibile avere due risposte corrette ^^ – Artharos

+1

No prob. :) Speriamo che ognuna delle nostre risposte sia d'aiuto. –

+2

E copiarli è facile come sostituire "shutil.move" con "shutil.copy". – Karoh

6

Poiché nessuno dei precedenti ha funzionato per me, così 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) 
+0

Questo è l'unico che funziona – user1447414

+0

Quali scenari non ha funzionato per te quando si utilizzano altre risposte? – cgmb

+0

Vale la pena notare, se src ha un file con lo stesso nome di una directory in dst, questa soluzione metterà il file all'interno della directory che condivide il suo nome, mentre [la soluzione di Ray Vega] (http://stackoverflow.com/a/ 7420617/331041) lancia 'OSErrore: [Errno 21] È una directory'. – cgmb

0

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 utilizzando os.walk(), chiamando in modo ricorsivo 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 eliminati.

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) 
3

Se hai bisogno anche di sovrascrivere i file di sola lettura con l'utilizzo bandiera 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) 
Problemi correlati