Come spostare un file?


909

Ho esaminato l' osinterfaccia di Python , ma non sono riuscito a individuare un metodo per spostare un file. Come farei l'equivalente di $ mv ...in Python?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder

1
per quelli di voi che hanno familiarità con il comando di gnu-coreutilsmv , quello di Python shutil.moveha un caso limite in cui la shutil.movefunzione differisce. Vai qui per la scrittura completa . In breve, Python's shutil.movegenererà un'eccezione (ma gnu-coreutils mvno) quando la tua destinazione è una directory e la directory ha già un file con lo stesso nome della fonte (di nuovo per maggiori informazioni vedi il link fornito nella frase precedente ).
Trevor Boyd Smith l'

3
Che ne dici os.system("mv file1 file2")?
John Strood,

Risposte:


1340

os.rename(), shutil.move()oos.replace()

Tutti utilizzano la stessa sintassi:

import os
import shutil

os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.replace("path/to/current/file.foo", "path/to/new/destination/for/file.foo")

Si noti che è necessario includere il nome del file ( file.foo) negli argomenti di origine e destinazione. Se viene modificato, il file verrà rinominato e spostato.

Si noti inoltre che nei primi due casi la directory in cui viene creato il nuovo file deve già esistere. Su Windows, non deve esistere un file con quel nome o verrà sollevata un'eccezione, ma os.replace()sostituirà silenziosamente un file anche in quel caso.

Come è stato notato nei commenti su altre risposte, nella maggior parte dei casi shutil.movechiama semplicemente os.rename. Tuttavia, se la destinazione si trova su un disco diverso da quello di origine, verrà invece copiato e quindi eliminato il file di origine.


8
Sono l'unico a pensare che os.rename non funzioni per le directory? Cito: "Se dst è una directory, OSError verrà generato."
Fabian,

33
shutil.movelavora per le directory. È possibile utilizzare il percorso relativo shutil.move(f.name, "tmp/")o il percorso completo shutil.move(f.name, "/Users/hello/tmp/"), non utilizzare ~ nel percorso, verificato in python2.7.9, Mac OS X.
whyisyoung

3
~è un costrutto di shell e non ha nulla a che fare con i percorsi dei file in sé, se non come una convenzione fuori luogo. Se vuoi davvero coinvolgere la tua home directory, usa os.getenv('HOME')invece, concatenandola con parti del tuo percorso desiderato, se necessario.
AMN

15
È sempre possibile utilizzare os.path.expanduser()per espandere correttamente " ~" in base alle regole specifiche del sistema operativo. Molto più ordinato dal momento che %HOME%non è sempre impostato su Windows.
ig0774,

14
os.renamenon gestirà i file su diversi dispositivi. Utilizzare shutil.movese non si è certi che l'origine e il file di destinazione siano sullo stesso dispositivo.
Giuseppe Scrivano,

244

Sebbene os.rename()e shutil.move()rinominino entrambi i file, il comando più vicino al comando mv Unix è shutil.move(). La differenza è che os.rename()non funziona se l'origine e la destinazione si trovano su dischi diversi, mentre shutil.move()non importa quale disco sono i file.


75
shutil.move()utilizza os.rename()se la destinazione si trova sul filesystem corrente. In caso contrario, shutil.move()copia l'origine nella destinazione utilizzando shutil.copy2()e quindi rimuove l'origine.
interruzione di riga

8
Fai attenzione a capire che shutil.copy2()non è possibile copiare tutti i metadati dei file , quindi se ciò accade è come farlo cp -pe quindi rm, mi accorgo.
ore

9
Attenzione: shutil.move in Python 2.7.3 ha esito negativo se la destinazione esiste già. Quindi, se ciò è possibile, rileva l'errore o rimuovi manualmente il file / dir, quindi esegui lo spostamento.
Dana,

36

Per os.rename o shutil.move dovrai importare il modulo. Non è necessario alcun carattere * per spostare tutti i file.

Abbiamo una cartella in / opt / awesome chiamata source con un file chiamato awesome.txt.

in /opt/awesome
  ls
source
  ls source
awesome.txt

python 
>>> source = '/opt/awesome/source'
>>> destination = '/opt/awesome/destination'
>>> import os
>>> os.rename(source, destination)
>>> os.listdir('/opt/awesome')
['destination']

Abbiamo usato os.listdir per vedere che il nome della cartella in realtà è cambiato. Ecco lo shutil che riporta la destinazione alla fonte.

>>> import shutil
>>> shutil.move(destination, source)
>>> os.listdir('/opt/awesome/source')
['awesome.txt']

Questa volta ho controllato nella cartella di origine per essere sicuro che il file awesome.txt che ho creato esista. È qui :)

Ora abbiamo spostato una cartella e i suoi file da un'origine a una destinazione e viceversa.


4
docs.python.org/2/library/shutil.html Questa documentazione mostra che hai cambiato i parametri per il metodo shutil.move.
mac10688,

1
Ho usato la destinazione e la fonte invertita per vedere che i file si sono spostati dalla fonte e poi di nuovo ad essa .... Ho potuto vedere come ciò non è chiaro.
jmontross,


14

Questo è quello che sto usando al momento:

import os, shutil
path = "/volume1/Users/Transfer/"
moveto = "/volume1/Users/Drive_Transfer/"
files = os.listdir(path)
files.sort()
for f in files:
    src = path+f
    dst = moveto+f
    shutil.move(src,dst)

Ora perfettamente funzionante. Spero che questo ti aiuti.

Modificare:

L'ho trasformato in una funzione, che accetta una directory di origine e di destinazione, rendendo la cartella di destinazione se non esiste e sposta i file. Consente anche il filtraggio dei file src, ad esempio se si desidera spostare solo le immagini, quindi si utilizza il modello '*.jpg', per impostazione predefinita, sposta tutto nella directory

import os, shutil, pathlib, fnmatch

def move_dir(src: str, dst: str, pattern: str = '*'):
    if not os.path.isdir(dst):
        pathlib.Path(dst).mkdir(parents=True, exist_ok=True)
    for f in fnmatch.filter(os.listdir(src), pattern):
        shutil.move(os.path.join(src, f), os.path.join(dst, f))

1
Puoi facilmente trasformarlo in una mossa filtrata usando fnmatch.filter (), vedi la mia modifica. Inoltre, è meglio usare al os.path.join(parent_path, filename)posto della concatenazione di stringhe per evitare problemi multipiattaforma
iggy12345

11

La risposta accettata non è quella giusta, perché la domanda non riguarda la ridenominazione di un file in un file, ma lo spostamento di molti file in una directory. shutil.movefarà il lavoro, ma a questo scopo os.renameè inutile (come indicato nei commenti) perché la destinazione deve avere un nome file esplicito.


Non inutile, richiede semplicemente più lavoro per farlo spostare più file. È possibile ottenere i nomi dei file con os.path.basename(my_file_path)e le directory dei file con os.path.dirname(my_file_path). Inoltre, l'OP non ha chiarito molto se voleva spostare più file. Ha menzionato lo spostamento di un solo file nella domanda, ma il suo codice di esempio implicava lo spostamento di più file.
Jacques Mathieu,

2

Sulla base della risposta qui descritta , l'utilizzo subprocessè un'altra opzione.

Qualcosa come questo:

subprocess.call("mv %s %s" % (source_files, destination_folder), shell=True)

Sono curioso di conoscere i pro e i contro di questo metodo rispetto a shutil. Dal momento che nel mio caso sto già usando subprocessper altri motivi e sembra funzionare, sono propenso a seguirlo.

Forse dipende dal sistema?


2
Credo che questo dipenda dal sistema. Non vedo mvessere utilizzato con successo su un sistema operativo Windows.
Joshua Schlichting,

0

Questa è una soluzione che non consente l' shellutilizzo mv.

import subprocess

source      = 'pathToCurrent/file.foo'
destination = 'pathToNew/file.foo'

p = subprocess.Popen(['mv', source, destination], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
res = p.communicate()[0].decode('utf-8').strip()

if p.returncode:
    print 'ERROR: ' + res

-2
  import os,shutil

  current_path = "" ## source path

  new_path = "" ## destination path

  os.chdir(current_path)

  for files in os.listdir():

        os.rename(files, new_path+'{}'.format(f))
        shutil.move(files, new_path+'{}'.format(f)) ## to move files from 

disco diverso es. C: -> D:


se stai usando Python3. # puoi usare la nuova intrerpolazione f-string: f"{new_path}{f}"ma dato che non hai testo statico nella tua stringa, questo potrebbe essere più lavoro .... Ho cercato di prendere l'abitudine di usare stringhe f però.
jusopi,

Intendi file invece di f?
Matteo,
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.