Comment déplacer un fichier?

910

J'ai regardé dans l' osinterface Python , mais je n'ai pas pu trouver de méthode pour déplacer un fichier. Comment pourrais-je faire l'équivalent de $ mv ...Python?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder
David542
la source
1
pour ceux qui sont familiers avec Gnu-coreutils mvde commande , de python shutil.movea un cas de bord où la shutil.movefonction diffère. Allez ici pour un compte rendu complet . En un mot, Python shutil.movelèvera une exception (mais pas gnu-coreutils mv) lorsque votre destination est un répertoire et que le répertoire a déjà un fichier avec le même nom que la source (encore une fois pour plus d'informations, voir le lien fourni dans la phrase précédente ).
Trevor Boyd Smith
3
Et alors os.system("mv file1 file2")?
John Strood

Réponses:

1340

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

Tous utilisent la même syntaxe:

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

Notez que vous devez inclure le nom de fichier ( file.foo) dans les arguments source et destination. S'il est modifié, le fichier sera renommé et déplacé.

Notez également que dans les deux premiers cas, le répertoire dans lequel le nouveau fichier est créé doit déjà exister. Sous Windows, un fichier portant ce nom ne doit pas exister ou une exception sera déclenchée, mais os.replace()remplacera silencieusement un fichier même dans cette occurrence.

Comme cela a été noté dans les commentaires sur d'autres réponses, il shutil.movesuffit d'appeler os.renamedans la plupart des cas. Cependant, si la destination se trouve sur un disque différent de la source, elle copiera puis supprimera le fichier source.

ig0774
la source
8
Suis-je le seul à penser que os.rename ne fonctionne pas pour les répertoires? Je cite: "Si dst est un répertoire, OSError sera levé."
Fabian
33
shutil.movefonctionne pour les répertoires. Vous pouvez utiliser un chemin relatif shutil.move(f.name, "tmp/")ou un chemin complet shutil.move(f.name, "/Users/hello/tmp/"), ne pas utiliser ~ dans le chemin, vérifié dans python2.7.9, Mac OS X.
whyisyoung
3
~est une construction shell, et n'a rien à voir avec les chemins de fichiers en soi, sauf comme une convention mal placée. Si vous voulez vraiment impliquer votre répertoire personnel, utilisez-le à la os.getenv('HOME')place, en le concaténant avec des parties du chemin souhaité, si nécessaire.
amn
15
Vous pouvez toujours utiliser os.path.expanduser()pour développer correctement le ' ~' selon les règles spécifiques au système d'exploitation. Beaucoup plus soigné car il %HOME%n'est pas toujours installé sur Windows.
ig0774
14
os.renamene traitera pas les fichiers sur différents appareils. À utiliser shutil.movesi vous n'êtes pas sûr que la source et le fichier de destination se trouvent sur le même appareil.
Giuseppe Scrivano
244

Bien os.rename()que shutil.move()les deux renomment les fichiers, la commande la plus proche de la commande mv Unix est shutil.move(). La différence est que os.rename()cela ne fonctionne pas si la source et la destination se trouvent sur des disques différents, shutil.move()sans se soucier du disque sur lequel se trouvent les fichiers.

Jim Calfas
la source
75
shutil.move()utilise os.rename()si la destination se trouve sur le système de fichiers actuel. Sinon, shutil.move()copie la source vers la destination à l'aide shutil.copy2(), puis supprime la source.
coupure de ligne
8
Prenez soin de réaliser que shutil.copy2()vous ne pouvez pas copier toutes les métadonnées de fichier , donc si cela se produit, c'est comme faire cp -pet ensuite rm, je comprends.
2rs2ts
9
Attention: shutil.move en Python 2.7.3 échoue si la destination existe déjà. Donc, si cela est possible, détectez l'erreur ou supprimez manuellement le fichier / répertoire, puis effectuez le déplacement.
Dana
36

Pour os.rename ou shutil.move, vous devrez importer le module. Aucun caractère * n'est nécessaire pour déplacer tous les fichiers.

Nous avons un dossier dans / opt / awesome appelé source avec un fichier nommé 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']

Nous avons utilisé os.listdir pour voir que le nom du dossier a en fait changé. Voici la fermeture de la destination vers la source.

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

Cette fois, j'ai vérifié dans le dossier source pour m'assurer que le fichier awesome.txt que j'ai créé existe. C'est là :)

Nous avons maintenant déplacé un dossier et ses fichiers d'une source vers une destination et vice-versa.

jmontross
la source
4
docs.python.org/2/library/shutil.html Cette documentation montre que vous avez changé vos paramètres pour la méthode shutil.move.
mac10688
1
J'ai utilisé la destination et la source inversées pour voir que les fichiers ont été déplacés de la source, puis y revenir .... Je pouvais voir comment cela n'était pas clair.
jmontross
34

Après Python 3.4, vous pouvez également utiliser pathlibla classe de Pathpour déplacer le fichier.

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
la source
3
Importer "depuis pathlib import Path" fonctionne bien :)
Touhid
14

Voici ce que j'utilise en ce moment:

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)

Maintenant entièrement fonctionnel. J'espère que cela vous aidera.

Éditer:

J'ai transformé cela en une fonction, qui accepte un répertoire source et de destination, créant le dossier de destination s'il n'existe pas, et déplace les fichiers. Permet également le filtrage des fichiers src, par exemple si vous ne souhaitez déplacer que des images, alors vous utilisez le motif '*.jpg', par défaut, il déplace tout dans le répertoire

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
la source
1
Vous pouvez facilement transformer cela en un mouvement filtré en utilisant fnmatch.filter (), voir ma modification. En outre, il est préférable d'utiliser os.path.join(parent_path, filename)au lieu de la concaténation de chaînes pour éviter les problèmes multiplates-formes
iggy12345
11

La réponse acceptée n'est pas la bonne, car la question n'est pas de renommer un fichier en fichier, mais de déplacer de nombreux fichiers dans un répertoire. shutil.movefera le travail, mais à cet effet os.renameest inutile (comme indiqué dans les commentaires) car la destination doit avoir un nom de fichier explicite.

Javier Palacios
la source
Pas inutile, nécessite simplement plus de travail pour le faire déplacer plusieurs fichiers. Vous pouvez obtenir les noms de fichiers avec os.path.basename(my_file_path)et les répertoires de fichiers avec os.path.dirname(my_file_path). De plus, le PO n'a pas précisé clairement s'il souhaitait déplacer plusieurs fichiers. Il a mentionné le déplacement d'un seul fichier dans la question, mais son exemple de code impliquait le déplacement de plusieurs fichiers.
Jacques Mathieu
2

Sur la base de la réponse décrite ici , l'utilisation subprocessest une autre option.

Quelque chose comme ça:

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

Je suis curieux de connaître les avantages et les inconvénients de cette méthode par rapport à shutil. Étant donné que dans mon cas, j'utilise déjà subprocesspour d'autres raisons et que cela semble fonctionner, je suis enclin à m'en tenir à cela.

Cela dépend-il du système peut-être?

Facture
la source
2
Je crois que cela dépendrait du système. Je ne vois pas mvêtre utilisé avec succès sur un système d'exploitation Windows.
Joshua Schlichting
0

C'est une solution qui ne permet pas d' shellutiliser 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
la source
-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 

disque différent ex. C: -> D:

Ned Slark
la source
si vous utilisez Python3. # vous pouvez utiliser la nouvelle intrerpolation de f-string: f"{new_path}{f}"mais étant donné que vous n'avez pas de texte statique dans votre chaîne, cela peut être plus de travail .... J'ai essayé de prendre l'habitude d'utiliser f-strings cependant.
jusopi
Voulez-vous dire fichier au lieu de f?
Matthew