Bagaimana cara memindahkan file?

909

Saya melihat ke osantarmuka Python , tetapi tidak dapat menemukan metode untuk memindahkan file. Bagaimana saya melakukan yang setara dengan $ mv ...di Python?

>>> source_files = '/PATH/TO/FOLDER/*'
>>> destination_folder = 'PATH/TO/FOLDER'
>>> # equivalent of $ mv source_files destination_folder
David542
sumber
1
Bagi Anda yang terbiasa dengan perintah gnu-coreutilsmv , python shutil.movememiliki satu sisi kasus di mana shutil.movefungsinya berbeda. Buka di sini untuk menulis lengkap . Singkatnya, Python shutil.moveakan memunculkan pengecualian (tetapi gnu-coreutils mvtidak akan) ketika tujuan Anda adalah direktori dan direktori sudah memiliki file dengan nama yang sama dengan sumber (sekali lagi untuk info lebih lanjut lihat tautan yang disediakan dalam kalimat sebelumnya ).
Trevor Boyd Smith
3
Bagaimana dengan os.system("mv file1 file2")?
John Strood

Jawaban:

1340

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

Semua menggunakan sintaks yang sama:

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

Perhatikan bahwa Anda harus memasukkan nama file ( file.foo) di argumen sumber dan tujuan. Jika diubah, file akan diganti namanya juga dipindahkan.

Perhatikan juga bahwa dalam dua kasus pertama direktori di mana file baru sedang dibuat harus sudah ada. Di Windows, file dengan nama itu tidak boleh ada atau pengecualian akan dimunculkan, tetapi os.replace()akan diam-diam mengganti file bahkan dalam kejadian itu.

Seperti yang telah dicatat dalam komentar pada jawaban lain, shutil.movecukup telepon os.renamedalam banyak kasus. Namun, jika tujuan berada pada disk yang berbeda dari sumber, ia akan menyalin dan kemudian menghapus file sumber.

ig0774
sumber
8
Apakah saya satu-satunya yang menganggap os.rename tidak berfungsi untuk direktori? Saya kutip: "Jika dst adalah direktori, OSError akan dimunculkan."
Fabian
33
shutil.moveberfungsi untuk direktori. Anda dapat menggunakan jalur relatif shutil.move(f.name, "tmp/")atau jalur penuh shutil.move(f.name, "/Users/hello/tmp/"), jangan gunakan ~ di jalur, diperiksa di python2.7.9, Mac OS X.
whyisyoung
3
~adalah shell konstruksi, dan tidak ada hubungannya dengan jalur file per se, selain sebagai konvensi salah tempat. Jika Anda benar-benar ingin melibatkan direktori home Anda, gunakan os.getenv('HOME')saja, gabungkan dengan bagian dari jalur yang Anda inginkan, jika perlu.
amn
15
Anda selalu dapat menggunakan os.path.expanduser()untuk memperluas ' ~' sesuai dengan aturan os-spesifik dengan benar. Lebih rapi karena %HOME%tidak selalu diatur pada Windows.
ig0774
14
os.renametidak akan menangani file di berbagai perangkat. Gunakan shutil.movejika Anda tidak yakin sumber dan file tujuan berada pada perangkat yang sama.
Giuseppe Scrivano
244

Meskipun os.rename()dan shutil.move()akan sama-sama mengganti nama file, perintah yang paling dekat dengan perintah Unix mv adalah shutil.move(). Perbedaannya adalah bahwa os.rename()tidak berfungsi jika sumber dan tujuan berada pada disk yang berbeda, sementara shutil.move()tidak peduli apa disk file tersebut.

Jim Calfas
sumber
75
shutil.move()digunakan os.rename()jika tujuannya adalah pada sistem file saat ini. Jika tidak, shutil.move()salin sumber ke tujuan menggunakan shutil.copy2()dan kemudian hapus sumbernya.
line break
8
Berhati-hatilah untuk menyadari bahwa shutil.copy2()tidak dapat menyalin semua metadata file , jadi jika itu terjadi, itu seperti melakukan cp -pdan kemudian rm, saya kumpulkan.
2rs2ts
9
Sadarilah: shutil.move dengan Python 2.7.3 gagal jika tujuannya sudah ada. Jadi jika itu mungkin, baik menangkap kesalahan, atau secara manual menghapus file / dir, kemudian lakukan langkah.
Dana
36

Untuk os.rename atau shutil.move Anda perlu mengimpor modul. Tidak diperlukan karakter * untuk memindahkan semua file.

Kami memiliki folder di / opt / awesome yang disebut sumber dengan satu file bernama 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']

Kami menggunakan os.listdir untuk melihat bahwa nama folder sebenarnya berubah. Inilah shutil yang memindahkan tujuan kembali ke sumber.

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

Kali ini saya memeriksa di dalam folder sumber untuk memastikan file awesome.txt yang saya buat ada. Itu di sana :)

Sekarang kami telah memindahkan folder dan file-file dari sumber ke tujuan dan kembali lagi.

jmontross
sumber
4
docs.python.org/2/library/shutil.html Dokumentasi ini menunjukkan bahwa Anda memiliki Anda parameter Anda diaktifkan untuk metode shutil.move.
mac10688
1
Saya menggunakan tujuan dan sumber terbalik untuk melihat bahwa file dipindahkan dari sumber dan kemudian kembali ke sana .... Saya bisa melihat bagaimana itu tidak jelas.
jmontross
34

Setelah Python 3.4, Anda juga dapat menggunakan pathlibkelas Pathuntuk memindahkan file.

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

Buah bulan
sumber
3
Untuk mengimpor "dari pathlib impor Path" berfungsi dengan baik :)
Touhid
14

Inilah yang saya gunakan saat ini:

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)

Sekarang berfungsi penuh. Semoga ini bisa membantu Anda.

Edit:

Saya telah mengubah ini menjadi fungsi, yang menerima direktori sumber dan tujuan, membuat folder tujuan jika tidak ada, dan memindahkan file. Juga memungkinkan untuk memfilter file src, misalnya jika Anda hanya ingin memindahkan gambar, maka Anda menggunakan pola '*.jpg', secara default, itu akan memindahkan semua yang ada di direktori

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
sumber
1
Anda dapat dengan mudah mengubah ini menjadi langkah yang difilter dengan menggunakan fnmatch.filter (), lihat edit saya. Juga, yang terbaik untuk digunakan os.path.join(parent_path, filename)daripada penggabungan string untuk menghindari masalah lintas platform
iggy12345
11

Jawaban yang diterima bukan yang benar, karena pertanyaannya bukan tentang mengubah nama file menjadi file, tetapi memindahkan banyak file ke direktori. shutil.moveakan melakukan pekerjaan, tetapi untuk tujuan os.renameini tidak berguna (sebagaimana dinyatakan pada komentar) karena tujuan harus memiliki nama file yang eksplisit.

Javier Palacios
sumber
Tidak sia-sia, hanya membutuhkan lebih banyak pekerjaan untuk mendapatkannya untuk memindahkan banyak file. Anda bisa mendapatkan nama file os.path.basename(my_file_path)dan direktori file os.path.dirname(my_file_path). Selain itu, tidak dibuat sangat jelas oleh OP jika dia ingin memindahkan banyak file. Dia menyebutkan hanya memindahkan satu file dalam pertanyaan, tetapi kode contohnya menyiratkan memindahkan beberapa file.
Jacques Mathieu
2

Berdasarkan jawaban yang dijelaskan di sini , menggunakan subprocessadalah pilihan lain.

Sesuatu seperti ini:

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

Saya ingin tahu pro dan kontra tentang metode ini dibandingkan dengan shutil. Karena dalam kasus saya, saya sudah menggunakan subprocessuntuk alasan lain dan tampaknya berhasil, saya cenderung mematuhinya.

Apakah ini tergantung pada sistem?

Tagihan
sumber
2
Saya percaya ini akan tergantung pada sistem. Saya tidak melihat mvberhasil digunakan pada sistem operasi windows.
Joshua Schlichting
0

Ini adalah solusi, yang tidak memungkinkan shelldigunakan 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
sumber
-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 

disk yang berbeda ex. C: -> D:

Ned Slark
sumber
jika Anda menggunakan Python3. # Anda dapat menggunakan intrerpolasi f-string baru: f"{new_path}{f}"tetapi mengingat Anda tidak memiliki teks statis di string Anda, ini mungkin lebih banyak pekerjaan .... Saya sudah mencoba membiasakan diri menggunakan f-string meskipun.
jusopi
Apakah maksud Anda file bukan f?
Matius