Come copio un file in Python?


2478

Come copio un file in Python?

Non sono riuscito a trovare nulla sotto os.


117
Sembra che cp non sia una chiamata di sistema e quindi non appartenga al modulo os. È un comando shell, quindi viene inserito nel modulo shutil.
waldol1,

Risposte:


3011

shutilha molti metodi che puoi usare. Uno dei quali è:

from shutil import copyfile
copyfile(src, dst)
  • Copia il contenuto del file denominato src in un file chiamato dst .
  • La posizione di destinazione deve essere scrivibile; in caso contrario, verrà sollevata un'eccezione IOError .
  • Se dst esiste già, verrà sostituito.
  • File speciali come dispositivi a caratteri o blocchi e pipe non possono essere copiati con questa funzione.
  • Con copy , src e dst sono nomi di percorso dati come stringhe .

Se si utilizzano le os.pathoperazioni, utilizzare copyanziché copyfile. copyfilesi accettano solo le stringhe .


147
Qual'è la differenza tra copy e copyfile?
Matt,

387
in copy (src, dst) il dst può essere una directory.
Owen,

41
Nota che non tutti i metadati verranno copiati, a seconda della tua piattaforma.
Kevin Horn,

12
Si noti che non si tratta di un'operazione atomica. Fai attenzione ad usarlo in un'applicazione filettata.
waterbyte,

4
Si noti che non può gestire abbreviazioni come ~, ma può gestire percorsi relativi
zwep

1253
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│     Function     │ Copies │   Copies  │Can use│   Destination  │
│                  │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy       │   No   │    Yes    │   No  │      Yes       │
│shutil.copyfile   │   No   │     No    │   No  │       No       │
│shutil.copy2      │  Yes   │    Yes    │   No  │      Yes       │
│shutil.copyfileobj│   No   │     No    │  Yes  │       No       │
└──────────────────┴────────┴───────────┴───────┴────────────────┘

732

copy2(src,dst)è spesso più utile di copyfile(src,dst)perché:

  • consente dstdi essere una directory (anziché il nome file di destinazione completo), nel qual caso il nome base di srcviene utilizzato per creare il nuovo file;
  • conserva la modifica originale e le informazioni di accesso (mtime e atime) nei metadati del file (tuttavia, ciò comporta un leggero sovraccarico).

Ecco un breve esempio:

import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext

19
Sto provando a copiare casualmente 100k file da 1 milione di file. copyfileè considerevolmente più veloce dicopy2
Vijay

4
ho ragione a supporre che shutil.copy2('/dir/file.ext', '/new/dir/')(con la barra dopo il percorso target) rimuoverà l'ambiguità rispetto alla copia in un nuovo file chiamato "dir" o se il file viene inserito in una directory con quel nome?
Zak,

1
@Vijay Credo che questo sovraccarico sia dovuto alla copia dei metadati.
Jonathan H,

@Zak Non vi è alcuna ambiguità se /new/diresiste una directory esistente, vedere il commento di @ MatthewAlpert.
Jonathan H,

@Zak Hai ragione, l'aggiunta di una barra alla fine rimuove l'ambiguità. Se /new/dir/non esiste, Python lancerà un IsADirectoryError, altrimenti copia il file /new/dir/con il nome originale.
martonbognar,

125

È possibile utilizzare una delle funzioni di copia da shutil pacchetto:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
La funzione conserva i supporti accetta altre copie
                      directory delle autorizzazioni dest. file obj metadata  
-------------------------------------------------- ----------------------------
shutil.copy               ✔ ✔ ☐ ☐
 shutil.copy2              ✔ ✔ ☐ ✔
 shutil.copyfile           ☐ ☐ ☐ ☐
 shutil.copyfileobj        ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Esempio:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')

10
Solo curioso, come hai generato quella tabella?
Lightalchemist il

16
@lightalchemist Ho appena usato vim come scratchpad, ho copiato i simboli unicode usati da una tabella di Wikipedia e ho copiato il risultato nell'editor stackoverflow per la lucidatura finale.
Maxschlepzig,

3
In che modo differisce dalle altre risposte 2 anni prima? stackoverflow.com/a/30359308/674039
mercoledì

1
@wim, devi confrontare la mia risposta con la versione 2017 della risposta che hai collegato che era attuale quando ho pubblicato la mia risposta. Differenze principali: la mia risposta utilizza intestazioni di colonna migliori / più descrittive, il layout della tabella non è fonte di distrazione, include collegamenti diretti alla documentazione e ho aggiunto una colonna (cioè "accetta file obj").
maxschlepzig,

4
OK. YMMV, ma penso che cambiamenti estetici e miglioramenti minori come questi vengano fatti meglio come modifiche alle risposte esistenti, piuttosto che come duplicazione delle risposte.
mercoledì

104

In Python, puoi copiare i file usando


import os
import shutil
import subprocess

1) Copia dei file usando il shutilmodulo

shutil.copyfile firma

shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

# example    
shutil.copyfile('source.txt', 'destination.txt')

shutil.copy firma

shutil.copy(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy('source.txt', 'destination.txt')

shutil.copy2 firma

shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy2('source.txt', 'destination.txt')  

shutil.copyfileobj firma

shutil.copyfileobj(src_file_object, dest_file_object[, length])

# example
file_src = 'source.txt'  
f_src = open(file_src, 'rb')

file_dest = 'destination.txt'  
f_dest = open(file_dest, 'wb')

shutil.copyfileobj(f_src, f_dest)  

2) Copia dei file usando il osmodulo

os.popen firma

os.popen(cmd[, mode[, bufsize]])

# example
# In Unix/Linux
os.popen('cp source.txt destination.txt') 

# In Windows
os.popen('copy source.txt destination.txt')

os.system firma

os.system(command)


# In Linux/Unix
os.system('cp source.txt destination.txt')  

# In Windows
os.system('copy source.txt destination.txt')

3) Copia dei file usando il subprocessmodulo

subprocess.call firma

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True) 

# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)

subprocess.check_output firma

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)

# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)


9
L'uso di comandi a stringa singola è uno stile di codifica errato (flessibilità, affidabilità e sicurezza), invece utilizza la ['copy', sourcefile, destfile]sintassi laddove possibile, specialmente se i parametri provengono dall'input dell'utente.
Marcel Waldvogel,

8
Perché elenchi così tante cattive alternative alle funzioni di copia di shutil?
maxschlepzig,

6
shutil è integrato, non è necessario fornire alternative non portatili. La risposta potrebbe essere effettivamente migliorata rimuovendo le soluzioni dipendenti dal sistema e, dopo quella rimozione, questa risposta è solo una copia delle risposte esistenti / una copia della documentazione.
Jean-François Fabre

3
os.popenè obsoleto da un po 'di tempo. e check_outputnon restituisce lo stato ma l'output (che è vuoto nel caso di copy/cp)
Jean-François Fabre

2
shutil in realtà non copia i file. C'è un grosso grosso avvertimento proprio in cima alla documentazione . "questo significa che il proprietario e il gruppo di file vengono persi e gli ACL. Su Mac OS, il fork delle risorse e altri metadati non vengono utilizzati. Ciò significa che le risorse andranno perse e il tipo di file e i codici creatore non saranno corretti. Su Windows, proprietari di file, ACL e flussi di dati alternativi non vengono copiati. "
Gman,

96

La copia di un file è un'operazione relativamente semplice, come mostrato negli esempi seguenti, ma per questo è necessario utilizzare il modulo shutil stdlib .

def copyfileobj_example(source, dest, buffer_size=1024*1024):
    """      
    Copy a file from source to dest. source and dest
    must be file-like objects, i.e. any object with a read or
    write method, like for example StringIO.
    """
    while True:
        copy_buffer = source.read(buffer_size)
        if not copy_buffer:
            break
        dest.write(copy_buffer)

Se vuoi copiare per nome file puoi fare qualcosa del genere:

def copyfile_example(source, dest):
    # Beware, this example does not handle any edge cases!
    with open(source, 'rb') as src, open(dest, 'wb') as dst:
        copyfileobj_example(src, dst)

25
Ho notato qualche tempo fa che il modulo si chiama shutil (singolare) e non shutils (plurale), e infatti è in Python 2.3. Tuttavia lascio qui questa funzione come esempio.
pi.

4
La copia del contenuto di un file è un'operazione semplice. Copiare il file con i suoi metadati è tutt'altro che semplice, ancor più se si desidera essere multipiattaforma.
LaC,

3
Vero. Guardando i documenti di shutil, anche la funzione copyfile non copia i metadati.
pi.

3
Sì, non sono sicuro del motivo per cui non dovresti semplicemente copiare la fonte di shutil.copyfileobj. Inoltre, non è try, finallynecessario gestire la chiusura dei file dopo le eccezioni. Direi tuttavia che la tua funzione non dovrebbe essere responsabile dell'apertura e della chiusura dei file. Dovrebbe andare in una funzione wrapper, come il shutil.copyfilewrapping shutil.copyfileobj.
ErlVolton,

2
Il codice sopra riportato dovrebbe specificare destdi essere scrivibile:open(dest, 'wb')
user1016274,

69

Utilizzare il modulo shutil .

copyfile(src, dst)

Copia il contenuto del file denominato src in un file chiamato dst. La posizione di destinazione deve essere scrivibile; in caso contrario, verrà sollevata un'eccezione IOError. Se dst esiste già, verrà sostituito. File speciali come dispositivi a caratteri o blocchi e pipe non possono essere copiati con questa funzione. src e dst sono nomi di percorso dati come stringhe.

Dai un'occhiata a filesys per tutte le funzioni di gestione di file e directory disponibili nei moduli Python standard.


shutil in realtà non copia i file. C'è un grosso grosso avvertimento proprio in cima alla documentazione . "questo significa che il proprietario e il gruppo di file vengono persi e gli ACL. Su Mac OS, il fork delle risorse e altri metadati non vengono utilizzati. Ciò significa che le risorse andranno perse e il tipo di file e i codici creatore non saranno corretti. Su Windows, proprietari di file, ACL e flussi di dati alternativi non vengono copiati. "
Gman,

47

Esempio di copia di directory e file - Da Tim Golden's Python Stuff:

http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

import os
import shutil
import tempfile

filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2

shutil.copy (filename1, filename2)

if os.path.isfile (filename2): print "Success"

dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2

shutil.copytree (dirname1, dirname2)

if os.path.isdir (dirname2): print "Success"

24

In primo luogo, ho creato un completo cheat sheet dei metodi di shutil come riferimento.

shutil_methods =
{'copy':['shutil.copyfileobj',
          'shutil.copyfile',
          'shutil.copymode',
          'shutil.copystat',
          'shutil.copy',
          'shutil.copy2',
          'shutil.copytree',],
 'move':['shutil.rmtree',
         'shutil.move',],
 'exception': ['exception shutil.SameFileError',
                 'exception shutil.Error'],
 'others':['shutil.disk_usage',
             'shutil.chown',
             'shutil.which',
             'shutil.ignore_patterns',]
}

In secondo luogo, spiegare i metodi di copia negli esempi:

  1. shutil.copyfileobj(fsrc, fdst[, length]) manipolare oggetti aperti
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
    ...:      shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
  1. shutil.copyfile(src, dst, *, follow_symlinks=True) Copia e rinomina
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
  1. shutil.copy() Copia senza conservare i metadati
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
  1. shutil.copy2() Copia con la conservazione dei metadati
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
  1. shutil.copytree()

Copia ricorsivamente un intero albero di directory radicato su src, restituendo la directory di destinazione


1
shutil in realtà non copia i file. C'è un grosso grosso avvertimento proprio in cima alla documentazione . "questo significa che il proprietario e il gruppo di file vengono persi e gli ACL. Su Mac OS, il fork delle risorse e altri metadati non vengono utilizzati. Ciò significa che le risorse andranno perse e il tipo di file e i codici creatore non saranno corretti. Su Windows, proprietari di file, ACL e flussi di dati alternativi non vengono copiati. "
Gman,

19

Per file di piccole dimensioni e utilizzando solo i built-in python, è possibile utilizzare il seguente one-liner:

with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())

Come @maxschlepzig ha menzionato nei commenti seguenti, questo non è un modo ottimale per le applicazioni in cui il file è troppo grande o quando la memoria è critica, quindi la risposta di Swati dovrebbe essere preferita.


3
Questo legge il file sorgente completo in memoria prima di riscriverlo. Pertanto, ciò spreca inutilmente memoria per tutte le operazioni di copia file, tranne quelle più piccole.
maxschlepzig,

1
È vero? Penso .read()e .write()sono bufferizzati di default (almeno per CPython).
colonna sonora il

@soundstripe, Naturalmente questo è vero. Il fatto che l'oggetto file restituito da open()IO bufferizzato, per impostazione predefinita non ti aiuta qui, perché read()è specificato come: 'Se n è negativo o omesso, leggi fino a EOF.' Ciò significa che read()restituisce il contenuto completo del file come stringa.
maxschlepzig,

@maxschlepzig Ho capito il tuo punto e ammetto di non esserne consapevole. La ragione per cui ho fornito questa risposta è stata nel caso in cui qualcuno volesse fare una semplice copia di file usando solo i built-in, senza bisogno di importare un modulo per esso. Ovviamente l'ottimizzazione della memoria non dovrebbe essere un problema se si desidera questa opzione. Comunque grazie per averlo chiarito. Ho aggiornato la risposta di conseguenza.
yellow01

14

Puoi usare os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

o come l'ho fatto,

os.system('cp '+ rawfile + ' rawdata.dat')

dov'è rawfileil nome che avevo generato all'interno del programma.

Questa è una soluzione solo per Linux


10
questo non è portatile e non è necessario poiché puoi semplicemente usare shutil.
Corey Goldberg,

4
Anche quando shutilnon è disponibile - subprocess.run() (senza shell=True!) È la migliore alternativa a os.system().
maxschlepzig,

1
shutil è più portatile
Hiadore

1
subprocess.run()come suggerito da @maxschlepzig è un grande passo avanti quando si chiamano programmi esterni. Per flessibilità e sicurezza, tuttavia, utilizzare il ['cp', rawfile, 'rawdata.dat']modulo per passare la riga di comando. (Tuttavia, per la copia, shutilsi consiglia agli amici di chiamare un programma esterno.)
Marcel Waldvogel,

2
provalo con nomi di file con spazi all'interno.
Jean-François Fabre

11

Per file di grandi dimensioni, ciò che ho fatto è stato leggere il file riga per riga e leggere ogni riga in un array. Quindi, una volta che l'array ha raggiunto una determinata dimensione, aggiungerlo a un nuovo file.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

2
questo sembra un po 'ridondante poiché lo scrittore dovrebbe gestire il buffering. for l in open('file.txt','r'): output.write(l)dovrebbe funzionare trovare; basta impostare il buffer del flusso di output in base alle proprie esigenze. oppure puoi passare dai byte ripetendo ciclicamente un tentativo con output.write(read(n)); output.flush()dov'è nil numero di byte che desideri scrivere alla volta. entrambi questi non hanno anche una condizione per verificare quale sia un bonus.
possiede il

1
Sì, ma ho pensato che forse questo potrebbe essere più facile da capire perché copia intere linee piuttosto che parti di esse (nel caso in cui non sappiamo quanti byte è ogni linea).
ytpillai,

Verissimo. La codifica per l'insegnamento e la codifica per l'efficienza sono molto diverse.
possiede

1
guardando la fonte - le scritture call scrivono, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c . Inoltre, il flusso di file è già aperto, quindi scrivere non dovrebbe riaprirlo ogni volta.
possiede

2
Questo è terribile. Fa lavori inutili senza una buona ragione. Non funziona con file arbitrari. La copia non è identica a byte se l'input ha terminazioni di linea insolite su sistemi come Windows. Perché pensi che questo potrebbe essere più facile da capire di una chiamata a una funzione di copia in shutil? Anche quando si ignora shutil, un semplice ciclo di lettura / scrittura a blocchi (usando IO non bufferizzato) è semplice, sarebbe efficiente e avrebbe molto più senso di così, e quindi è sicuramente più facile da insegnare e capire.
maxschlepzig,

11
from subprocess import call
call("cp -p <file> <file>", shell=True)

10
Questo dipende dalla piattaforma, quindi non vorrei usarlo.
Kevin Meier,

5
Tale callnon è sicuro. Si prega di fare riferimento al documento sui sottoprocessi al riguardo.
buhtz,

2
questo non è portatile e non è necessario poiché puoi semplicemente usare shutil.
Corey Goldberg,

2
Allora perché Python?
Baris Demiray,

Forse rilevi il sistema operativo prima di iniziare (che si tratti di DOS o Unix, perché quelli sono i due più utilizzati)
MilkyWay90

8

A partire da Python 3.5 è possibile effettuare le seguenti operazioni per file di piccole dimensioni (ad esempio: file di testo, jpeg di piccole dimensioni):

from pathlib import Path

source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())

write_bytes sovrascriverà qualunque cosa fosse nella posizione di destinazione


2
E poi qualcuno usa il codice (accidentalmente o intenzionalmente) su un file di grandi dimensioni ... L'uso delle funzioni di shutilgestisce tutti i casi speciali per te e ti dà tranquillità.
Marcel Waldvogel,

4
almeno non ripete ripetutamente le stesse soluzioni.
Jean-François Fabre

6
open(destination, 'wb').write(open(source, 'rb').read())

Apri il file sorgente in modalità lettura e scrivi sul file di destinazione in modalità scrittura.


1
L'idea è buona e il codice è bello, ma una corretta funzione copy () può fare più cose, come copiare gli attributi (+ x bit) o, ad esempio, cancellare i byte già copiati nel caso in cui venga trovata una condizione piena del disco .
Raúl Salinas-Monteagudo,

1
Tutte le risposte hanno bisogno di spiegazioni, anche se è una frase. Nessuna spiegazione costituisce un precedente negativo e non è utile per comprendere il programma. E se arrivasse un noob completo di Python e lo vedesse, voleva usarlo, ma non poteva perché non lo capivano? Vuoi essere d'aiuto a tutti nelle tue risposte.
connectyourcharger

1
Non manca questo .close()su tutti quei open(...)s?
luckydonald

Non c'è bisogno di .close (), dato che NON STORIAMO l'oggetto puntatore del file da nessuna parte (né per il file src né per il file di destinazione).
S471,


-3

Python offre funzioni integrate per copiare facilmente i file utilizzando le utility Shell del sistema operativo.

Il seguente comando viene utilizzato per copiare il file

shutil.copy(src,dst)

Il comando seguente viene utilizzato per copiare il file con le informazioni MetaData

shutil.copystat(src,dst)

Dovresti copyquindi eseguirlo copystatper conservare i metadati del file. In Python 3.3+ copystatcopia anche gli attributi estesi.
ingyhere
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.