Wie verschiebe ich eine Datei?

909

Ich habe in die Python- osOberfläche geschaut , konnte jedoch keine Methode zum Verschieben einer Datei finden. Wie würde ich das Äquivalent von $ mv ...in Python tun ?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder
David542
quelle
1
Für diejenigen unter Ihnen, die mit dem mvBefehl von gnu-coreutils vertraut sind , hat Python shutil.moveeinen Randfall, in dem sich die shutil.moveFunktion unterscheidet. Hier finden Sie alle Informationen . Kurz gesagt, Pythons shutil.movelöst eine Ausnahme aus (Gnu-Coreutils mvjedoch nicht), wenn Ihr Ziel ein Verzeichnis ist und das Verzeichnis bereits eine Datei mit demselben Namen wie die Quelle enthält (weitere Informationen finden Sie unter dem im vorherigen Satz angegebenen Link ).
Trevor Boyd Smith
3
Wie wäre es os.system("mv file1 file2")?
John Strood

Antworten:

1340

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

Alle verwenden dieselbe Syntax:

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

Beachten Sie, dass Sie den Dateinamen ( file.foo) sowohl in das Quell- als auch in das Zielargument aufnehmen müssen. Wenn es geändert wird, wird die Datei umbenannt und verschoben.

Beachten Sie auch, dass in den ersten beiden Fällen das Verzeichnis, in dem die neue Datei erstellt wird, bereits vorhanden sein muss. Unter Windows darf eine Datei mit diesem Namen nicht vorhanden sein, da sonst eine Ausnahme os.replace()ausgelöst wird. Eine Datei wird jedoch auch in diesem Fall stillschweigend ersetzt.

Wie in Kommentaren zu anderen Antworten erwähnt, wird in den meisten Fällen shutil.moveeinfach angerufen os.rename. Befindet sich das Ziel jedoch auf einer anderen Festplatte als die Quelle, wird stattdessen die Quelldatei kopiert und anschließend gelöscht.

ig0774
quelle
8
Bin ich der einzige, der glaubt, dass os.rename nicht für Verzeichnisse funktioniert? Ich zitiere: "Wenn dst ein Verzeichnis ist, wird OSError ausgelöst."
Fabian
33
shutil.movefunktioniert für Verzeichnisse. Sie können relativen Pfad shutil.move(f.name, "tmp/")oder vollständigen Pfad verwenden shutil.move(f.name, "/Users/hello/tmp/"), nicht ~ im Pfad verwenden, überprüft in Python2.7.9, Mac OS X.
Whyisyoung
3
~ist ein Shell-Konstrukt und hat nichts mit Dateipfaden an sich zu tun, außer als falsch platzierte Konvention. Wenn Sie Ihr Home-Verzeichnis wirklich einbeziehen möchten, verwenden Sie es os.getenv('HOME')stattdessen und verknüpfen Sie es gegebenenfalls mit Teilen Ihres gewünschten Pfads.
Amn
15
Sie os.path.expanduser()können das ' ~' jederzeit nach os-spezifischen Regeln richtig erweitern . Viel ordentlicher, da %HOME%es unter Windows nicht immer eingestellt ist.
ig0774
14
os.renameverarbeitet keine Dateien auf verschiedenen Geräten. Verwenden shutil.moveSie diese Option, wenn Sie nicht sicher sind, ob sich die Quell- und die Zieldatei auf demselben Gerät befinden.
Giuseppe Scrivano
244

Obwohl os.rename()und shutil.move()werden beide Dateien umbenennen, lautet der Befehl, der dem Unix-Befehl mv am nächsten kommt shutil.move(). Der Unterschied besteht darin, dass os.rename()dies nicht funktioniert, wenn sich Quelle und Ziel auf unterschiedlichen Datenträgern befinden, während shutil.move()es egal ist, auf welchem ​​Datenträger sich die Dateien befinden.

Jim Calfas
quelle
75
shutil.move()wird verwendet, os.rename()wenn sich das Ziel im aktuellen Dateisystem befindet. Andernfalls wird shutil.move()die Quelle mithilfe von in das Ziel kopiert shutil.copy2()und anschließend entfernt.
Zeilenumbruch
8
Achten Sie darauf, dass shutil.copy2()nicht alle Dateimetadaten kopiert werden können. Wenn dies passiert, ist es so, cp -pund dann rmsammle ich.
2rs2ts
9
Beachten Sie: shutil.move in Python 2.7.3 schlägt fehl, wenn das Ziel bereits vorhanden ist. Wenn dies möglich ist, fangen Sie entweder den Fehler ab oder entfernen Sie die Datei / das Verzeichnis manuell. Verschieben Sie sie dann.
Dana
36

Für os.rename oder shutil.move müssen Sie das Modul importieren. Es ist kein * Zeichen erforderlich, um alle Dateien zu verschieben.

Wir haben einen Ordner unter / opt / awesome namens source mit einer Datei namens 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']

Wir haben os.listdir verwendet, um festzustellen, dass sich der Ordnername tatsächlich geändert hat. Hier ist das Shutil, das das Ziel zurück zur Quelle verschiebt.

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

Diesmal habe ich im Quellordner nachgesehen, ob die von mir erstellte Datei awesome.txt vorhanden ist. Es ist dort :)

Jetzt haben wir einen Ordner und seine Dateien von einer Quelle zu einem Ziel und wieder zurück verschoben.

jmontross
quelle
4
docs.python.org/2/library/shutil.html Diese Dokumentation zeigt, dass Sie Ihre Parameter für die Methode shutil.move geändert haben.
Mac10688
1
Ich habe das Ziel und die Quelle umgekehrt verwendet, um zu sehen, dass die Dateien von der Quelle und dann wieder dorthin verschoben wurden. Ich konnte sehen, wie unklar das ist.
Jmontross
34

Nach Python 3.4 können Sie die pathlibKlasse auch Pathzum Verschieben von Dateien verwenden.

from pathlib import Path

Path("path/to/current/file.foo").rename("path/to/new/destination/for/file.foo")

https://docs.python.org/3.4/library/pathlib.html#pathlib.Path.rename

MoonFruit
quelle
3
Das Importieren von "from pathlib import Path" funktioniert gut :)
Touhid
14

Dies ist, was ich im Moment benutze:

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)

Jetzt voll funktionsfähig. Hoffe das hilft dir.

Bearbeiten:

Ich habe daraus eine Funktion gemacht, die ein Quell- und Zielverzeichnis akzeptiert, den Zielordner erstellt, falls er nicht vorhanden ist, und die Dateien verschiebt. Ermöglicht auch das Filtern der src-Dateien. Wenn Sie beispielsweise nur Bilder verschieben möchten, verwenden Sie das Muster '*.jpg'. Standardmäßig wird alles im Verzeichnis verschoben

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))
Peter Vlaar
quelle
1
Sie können dies leicht in einen gefilterten Zug verwandeln, indem Sie fnmatch.filter () verwenden, siehe meine Bearbeitung. Es ist auch am besten, os.path.join(parent_path, filename)anstelle der Verkettung von Zeichenfolgen plattformübergreifende Probleme zu verwenden
iggy12345
11

Die akzeptierte Antwort ist nicht die richtige, da es bei der Frage nicht darum geht, eine Datei in eine Datei umzubenennen, sondern viele Dateien in ein Verzeichnis zu verschieben. shutil.movewird die Arbeit erledigen, ist aber für diesen Zweck os.renamenutzlos (wie in den Kommentaren angegeben), da das Ziel einen expliziten Dateinamen haben muss.

Javier Palacios
quelle
Nicht nutzlos, erfordert einfach mehr Arbeit, um mehrere Dateien zu verschieben. Sie können Dateinamen mit os.path.basename(my_file_path)und die Dateiverzeichnisse mit abrufen os.path.dirname(my_file_path). Außerdem wurde vom OP nicht sehr deutlich gemacht, ob er mehrere Dateien verschieben wollte. Er erwähnte das Verschieben nur einer Datei in der Frage, aber sein Beispielcode implizierte das Verschieben mehrerer Dateien.
Jacques Mathieu
2

Basierend auf der hier beschriebenen Antwort ist die Verwendung subprocesseine weitere Option.

Etwas wie das:

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

Ich bin gespannt auf die Vor- und Nachteile dieser Methode im Vergleich zu shutil. Da ich in meinem Fall bereits subprocessaus anderen Gründen benutze und es zu funktionieren scheint, neige ich dazu, mich daran zu halten.

Ist es vielleicht systemabhängig?

Rechnung
quelle
2
Ich glaube, das wäre systemabhängig. Ich sehe keine mverfolgreiche Verwendung unter einem Windows-Betriebssystem.
Joshua Schlichting
0

Dies ist eine Lösung, die die shellVerwendung nicht ermöglicht 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
alper
quelle
-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 

andere Platte ex. C: -> D:

Ned Slark
quelle
Wenn Sie Python3. # verwenden, können Sie die neue F-String-Interpolation verwenden. Da f"{new_path}{f}"Sie jedoch keinen statischen Text in Ihrem String haben, ist dies möglicherweise mehr Arbeit. Ich habe versucht, mich an die Gewohnheit zu gewöhnen F-Saiten allerdings.
Jusopi
Meinst du Datei statt f?
Matthew