Làm thế nào để di chuyển một tập tin?


909

Tôi đã xem xét osgiao diện Python , nhưng không thể xác định được phương thức để di chuyển tệp. Làm thế nào tôi có thể làm tương đương với $ mv ...Python?

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

1
Đối với những người quen thuộc với lệnh của gnu-coreutilsmv , python shutil.movecó một trường hợp cạnh có shutil.movechức năng khác nhau. Tới đây để viết đầy đủ lên . Tóm lại, Python shutil.movesẽ đưa ra một ngoại lệ (nhưng gnu-coreutils mvsẽ không) khi đích đến của bạn là một thư mục và thư mục đã có một tệp có cùng tên với nguồn (một lần nữa để biết thêm thông tin, hãy xem liên kết được cung cấp trong câu trước ).
Trevor Boyd Smith

3
Thế còn os.system("mv file1 file2")?
John Strood

Câu trả lời:


1340

os.rename(), shutil.move()hoặcos.replace()

Tất cả sử dụng cùng một cú pháp:

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

Lưu ý rằng bạn phải bao gồm tên tệp ( file.foo) trong cả đối số nguồn và đích. Nếu nó được thay đổi, tập tin sẽ được đổi tên cũng như di chuyển.

Cũng lưu ý rằng trong hai trường hợp đầu tiên, thư mục chứa tệp mới được tạo phải tồn tại. Trên Windows, một tệp có tên đó không được tồn tại hoặc một ngoại lệ sẽ được nêu ra, nhưng os.replace()sẽ âm thầm thay thế một tệp ngay cả trong lần xuất hiện đó.

Như đã được lưu ý trong các ý kiến ​​về các câu trả lời khác, shutil.movechỉ cần gọi os.renametrong hầu hết các trường hợp. Tuy nhiên, nếu đích nằm trên một đĩa khác với nguồn, thay vào đó, nó sẽ sao chép và sau đó xóa tệp nguồn.


8
Tôi có phải là người duy nhất nghĩ rằng os.rename không hoạt động cho các thư mục không? Tôi trích dẫn: "Nếu dst là một thư mục, OSError sẽ được nâng lên."
Fabian

33
shutil.movelàm việc cho các thư mục. Bạn có thể sử dụng đường dẫn tương đối shutil.move(f.name, "tmp/")hoặc đường dẫn đầy đủ shutil.move(f.name, "/Users/hello/tmp/"), không sử dụng ~ trong đường dẫn, đã kiểm tra trong python2.7.9, Mac OS X.
whyisyoung

3
~là một cấu trúc shell và không liên quan gì đến các đường dẫn tệp, ngoại trừ như một quy ước đặt sai vị trí. Nếu bạn thực sự muốn liên quan đến thư mục chính của mình, hãy sử dụng os.getenv('HOME')thay vào đó, nối nó với các phần của đường dẫn bạn muốn, nếu cần thiết.
Amn

15
Bạn luôn có thể sử dụng os.path.expanduser()để mở rộng ' ~' theo quy tắc cụ thể của os. Nhiều gọn gàng hơn vì %HOME%không phải lúc nào cũng được thiết lập trên Windows.
ig0774 24/07/2015

14
os.renamesẽ không xử lý các tập tin trên các thiết bị khác nhau. Sử dụng shutil.movenếu bạn không chắc chắn nguồn và tệp đích nằm trên cùng một thiết bị.
Giuseppe Scrivano

244

Mặc dù os.rename()shutil.move()cả hai sẽ đổi tên các tệp, lệnh gần nhất với lệnh mv Unix là shutil.move(). Sự khác biệt là os.rename()không hoạt động nếu nguồn và đích nằm trên các đĩa khác nhau, trong khi shutil.move()không quan tâm tệp nào được bật.


75
shutil.move()sử dụng os.rename()nếu đích đến trên hệ thống tập tin hiện tại. Mặt khác, shutil.move()sao chép nguồn đến đích bằng cách sử dụng shutil.copy2()và sau đó loại bỏ nguồn.
ngắt dòng

8
Hãy cẩn thận để nhận ra rằng shutil.copy2()không thể sao chép tất cả siêu dữ liệu tệp , vì vậy nếu điều đó xảy ra thì nó giống như làm cp -pvà sau đó rm, tôi thu thập.
2rs2ts

9
Lưu ý: shutil.move trong Python 2.7.3 không thành công nếu đích đã tồn tại. Vì vậy, nếu điều đó là có thể, hoặc bắt lỗi, hoặc xóa thủ công tệp / thư mục, sau đó thực hiện di chuyển.
Dana

36

Đối với os.rename hoặc shutil.move, bạn sẽ cần nhập mô-đun. Không có ký tự * là cần thiết để di chuyển tất cả các tệp.

Chúng tôi có một thư mục tại / opt / awesome được gọi là nguồn với một tệp có tên 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']

Chúng tôi đã sử dụng os.listdir để thấy rằng tên thư mục trên thực tế đã thay đổi. Đây là sự đóng cửa di chuyển điểm đến trở lại nguồn.

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

Lần này tôi đã kiểm tra bên trong thư mục nguồn để chắc chắn rằng tệp awesome.txt tôi đã tạo tồn tại. Nó ở đó :)

Bây giờ chúng tôi đã di chuyển một thư mục và các tệp của nó từ một nguồn đến đích và quay lại.


4
docs.python.org/2/library/shutil.html Tài liệu này cho thấy rằng bạn có bạn thông số của bạn chuyển cho phương pháp shutil.move.
mac10688

1
Tôi đã sử dụng đích và nguồn đảo ngược để thấy rằng các tệp được di chuyển từ nguồn và sau đó quay lại nó .... Tôi có thể thấy điều đó không rõ ràng.
jmontross


14

Đây là những gì tôi đang sử dụng tại thời điểm này:

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)

Bây giờ đầy đủ chức năng. Hy vọng điều này sẽ giúp bạn.

Biên tập:

Tôi đã biến điều này thành một hàm, chấp nhận thư mục nguồn và đích, tạo thư mục đích nếu nó không tồn tại và di chuyển các tệp. Cũng cho phép lọc các tệp src, ví dụ nếu bạn chỉ muốn di chuyển hình ảnh, thì bạn sử dụng mẫu '*.jpg', theo mặc định, nó di chuyển mọi thứ trong thư mục

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
Bạn có thể dễ dàng biến điều này thành một động thái được lọc bằng cách sử dụng fnmatch.filter (), xem chỉnh sửa của tôi. Ngoài ra, tốt nhất nên sử dụng os.path.join(parent_path, filename)thay vì nối chuỗi để tránh các sự cố đa nền tảng
iggy12345

11

Câu trả lời được chấp nhận không phải là câu trả lời đúng, bởi vì câu hỏi không phải là đổi tên một tệp thành một tệp, mà là chuyển nhiều tệp vào một thư mục. shutil.movesẽ thực hiện công việc, nhưng với mục đích os.renamenày là vô ích (như đã nêu trên các bình luận) vì đích phải có tên tệp rõ ràng.


Không vô dụng, đơn giản chỉ cần nhiều công việc hơn để khiến nó di chuyển nhiều tệp. Bạn có thể lấy tên tệp os.path.basename(my_file_path)và thư mục tệp với os.path.dirname(my_file_path). Ngoài ra, OP đã không làm rõ nếu anh ta muốn di chuyển nhiều tệp. Anh ta đề cập đến việc chỉ di chuyển một tệp trong câu hỏi, nhưng mã ví dụ của anh ta ngụ ý di chuyển nhiều tệp.
Jacques Mathieu

2

Dựa trên câu trả lời được mô tả ở đây , sử dụng subprocesslà một lựa chọn khác.

Một cái gì đó như thế này:

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

Tôi tò mò muốn biết pro và con của phương pháp này so với shutil. Vì trong trường hợp của tôi, tôi đã sử dụng subprocessvì những lý do khác và nó dường như hoạt động, tôi có xu hướng gắn bó với nó.

Có phụ thuộc hệ thống không?


2
Tôi tin rằng điều này sẽ phụ thuộc vào hệ thống. Tôi không thấy mvđược sử dụng thành công trên hệ điều hành windows.
Joshua Schlichting

0

Đây là giải pháp, không cho phép shellsử dụng 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 

đĩa khác nhau. C: -> D:


nếu bạn đang sử dụng Python3. # bạn có thể sử dụng phép nội suy chuỗi f mới: f"{new_path}{f}"nhưng cho rằng bạn không có văn bản tĩnh trong chuỗi của mình, điều này có thể sẽ hiệu quả hơn .... Tôi đã cố gắng tập thói quen sử dụng dây f mặc dù.
jusopi

Bạn có nghĩa là tập tin thay vì f?
Matthew
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.