Câu hỏi Làm thế nào để sao chép một tập tin trong python?


Làm cách nào để sao chép tệp bằng Python? Tôi không thể tìm thấy bất cứ điều gì dưới os.


1469
2017-09-23 19:23


gốc


Có vẻ như cp không phải là một cuộc gọi hệ thống và do đó không thuộc về mô-đun os. Nó là một lệnh shell, vì vậy nó được đặt trong module shutil. - waldol1


Các câu trả lời:


shutil có nhiều phương pháp bạn có thể sử dụng. Một trong số đó là:

from shutil import copyfile

copyfile(src, dst)

Sao chép nội dung của tệp có tên src vào một tệp có tên dst. Vị trí đích phải có thể ghi được; nếu không, một IOError ngoại lệ sẽ được nâng lên. Nếu dst đã tồn tại, nó sẽ được thay thế. Không thể sao chép các tệp đặc biệt như ký tự hoặc khối thiết bị và đường ống bằng chức năng này. src và dst là tên đường dẫn được cung cấp dưới dạng chuỗi.


1788
2017-09-23 19:25



Sự khác biệt giữa bản sao và copyfile là gì? - Matt
trong bản sao (src, dst) dst có thể là một thư mục. - Owen
Lưu ý rằng không phải tất cả siêu dữ liệu sẽ được sao chép, tùy thuộc vào nền tảng của bạn. - Kevin Horn
từ importilrror nhập khẩu shutil: không thể nhập tên copyFile - Mona Jalal
@MonaJalal Đó là trường hợp nhạy cảm, không sử dụng vốn F. - antonagestam


-----------------------------------------------------------------------------------
| Function          |Copies Metadata|Copies Permissions|Can Use Buffer|Dest Dir OK
-----------------------------------------------------------------------------------
| shutil.copy       |      No       |        Yes       |      No      |    Yes
-----------------------------------------------------------------------------------
| shutil.copyfile   |      No       |        No        |      No      |    No
-----------------------------------------------------------------------------------
| shutil.copy2      |      Yes      |        Yes       |      No      |    Yes
-----------------------------------------------------------------------------------
| shutil.copyfileobj|      No       |        No        |      Yes     |    No
-----------------------------------------------------------------------------------

554
2018-05-20 20:01



Cũng có thể thêm rằng bản sao và copy2 chấp nhận thư mục như là đích trái với copyfile mà yêu cầu để xác định tên đầy đủ. - Conchylicultor
@jezrael Trích xuất từ ​​tài liệu: dst must be the complete target file name; look at shutil.copy() for a copy that accepts a target directory path. (đây: docs.python.org/3/library/shutil.html#shutil.copyfile) - Conchylicultor


copy2(src,dst) thường hữu ích hơn copyfile(src,dst) bởi vì:

  • nó cho phép dst là một danh mục (thay vì tên tệp đích hoàn chỉnh), trong trường hợp này basename của src được sử dụng để tạo tệp mới;
  • nó bảo tồn các sửa đổi ban đầu và thông tin truy cập (mtime và atime) trong siêu dữ liệu tệp (tuy nhiên, điều này đi kèm với một chi phí nhỏ).

Đây là một ví dụ ngắn:

import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext

549
2017-09-23 19:29



Mặc dù tài liệu cảnh báo rằng copy2 không bảo toàn tất cả siêu dữ liệu, đây chỉ là những gì tôi cần vì tôi muốn các mục bạn liệt kê. Cảm ơn! - sage
Câu trả lời của bạn là một chút lừa đảo. Lựa chọn từ của bạn cho shutil.copy2('/dir/file.ext', '/new/dir') gợi ý rằng copy2 sẽ tạo một thư mục mới. Nhưng trong trường hợp này dir phải đã tồn tại như một danh mục hoặc cái gì đó khác file.ext sẽ được sao chép sang một tập tin gọi là dir. - Matthew Alpert
Tôi đang cố gắng sao chép ngẫu nhiên 100k tệp từ 1 triệu tệp. copyfile nhanh hơn đáng kể so với copy2 - Vijay
tôi có đúng là giả định rằng shutil.copy2('/dir/file.ext', '/new/dir/') (với dấu gạch chéo sau đường dẫn đích) sẽ loại bỏ sự mơ hồ về việc có sao chép sang một tệp mới có tên là "dir" hay để đưa tệp vào thư mục của tên đó không? - Zak
@Vijay Tôi tin rằng chi phí này là do sao chép siêu dữ liệu. - Sheljohn


Sao chép tệp là thao tác tương đối đơn giản như được minh họa trong các ví dụ bên dưới, nhưng thay vào đó bạn nên sử dụng -môđun stdlib đóng cho điều đó.

def copyfileobj_example(source, dest, buffer_size=1024*1024):
    """      
    Copy a file from source to dest. source and dest
    must be file-like objects, i.e. any object with a read or
    write method, like for example StringIO.
    """
    while True:
        copy_buffer = source.read(buffer_size)
        if not copy_buffer:
            break
        dest.write(copy_buffer)

Nếu bạn muốn sao chép theo tên tập tin bạn có thể làm một cái gì đó như thế này:

def copyfile_example(source, dest):
    # Beware, this example does not handle any edge cases!
    with open(source, 'rb') as src, open(dest, 'wb') as dst:
        copyfileobj_example(src, dst)

73
2017-09-24 07:21



Tôi nhận thấy một lúc trước rằng các mô-đun được gọi là shutil (số ít) và không đóng cửa (số nhiều), và thực sự nó Là trong Python 2.3. Tuy nhiên, tôi để chức năng này ở đây làm ví dụ. - pi.
Sao chép tệp nội dung là một hoạt động đơn giản. Sao chép tệp bằng siêu dữ liệu của tệp là bất kỳ điều gì nhưng đơn giản, thậm chí nhiều hơn thế nếu bạn muốn là nền tảng chéo. - LaC
Thật. Nhìn vào các tài liệu tắt, chức năng copyfile cũng sẽ không sao chép siêu dữ liệu. - pi.
BTW, nếu bạn muốn sao chép nội dung giữa hai đối tượng giống như tệp, có shutil.copyfileobj(fsrc, fdst) - Haroldo_OK
Có, tôi không chắc tại sao bạn không chỉ sao chép nguồn gốc của shutil.copyfileobj. Ngoài ra, bạn không có bất kỳ try, finally để xử lý đóng các tệp sau khi ngoại lệ. Tuy nhiên, tôi sẽ nói rằng chức năng của bạn không chịu trách nhiệm cho việc mở và đóng các tệp. Điều đó nên đi vào một hàm bao bọc, như thế nào shutil.copyfile kết thúc tốt đẹp shutil.copyfileobj. - ErlVolton


Sử dụng -môđun đóng.

copyfile(src, dst)

Sao chép nội dung của tệp có tên src vào tệp có tên dst. Vị trí đích phải có thể ghi được; nếu không, một ngoại lệ IOError sẽ được nâng lên. Nếu dst đã tồn tại, nó sẽ được thay thế. Không thể sao chép các tệp đặc biệt như ký tự hoặc khối thiết bị và đường ống bằng chức năng này. src và dst là các tên đường dẫn được cho là chuỗi.

Hãy xem filesys cho tất cả các hàm xử lý thư mục và tệp có sẵn trong các mô-đun Python chuẩn.


47
2017-09-23 19:27





Bạn có thể sử dụng một trong các hàm sao chép từ shutil gói:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chức năng bảo tồn hỗ trợ chấp nhận các bản sao khác
                      quyền thư mục dest. tệp siêu dữ liệu obj
―――――――――――――――――――――――――――――――――――――――――――――――――― ――――――――――――――――――――――――――――
shutil.copy                                            ☐ ☐
shutil.copy2                                           ☐
shutil.copyfile          ☐ ☐ ☐ ☐
shutil.copyfileobj       ☐ ☐ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Thí dụ:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')

40
2017-07-09 11:50





Ví dụ về tệp và thư mục - Từ nội dung Python của Tim Golden:

http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

import os
import shutil
import tempfile

filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2

shutil.copy (filename1, filename2)

if os.path.isfile (filename2): print "Success"

dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2

shutil.copytree (dirname1, dirname2)

if os.path.isdir (dirname2): print "Success"

36
2018-03-15 10:11





Xem mô-đun tắt máy. Nó chứa hàm copyfile(src, dst)


21
2017-09-23 19:27





Trong Python, bạn có thể sao chép các tập tin bằng cách sử dụng


import os
import shutil
import subprocess

1) Sao chép tệp bằng shutil mô-đun

shutil.copyfileChữ ký

shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

# example    
shutil.copyfile('source.txt', 'destination.txt')

shutil.copyChữ ký

shutil.copy(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy('source.txt', 'destination.txt')

shutil.copy2Chữ ký

shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy2('source.txt', 'destination.txt')  

shutil.copyfileobjChữ ký

shutil.copyfileobj(src_file_object, dest_file_object[, length])

# example
file_src = 'source.txt'  
f_src = open(file_src, 'rb')

file_dest = 'destination.txt'  
f_dest = open(file_dest, 'wb')

shutil.copyfileobj(f_src, f_dest)  

2) Sao chép tệp bằng os mô-đun

os.popenChữ ký

os.popen(cmd[, mode[, bufsize]])

# example
# In Unix/Linux
os.popen('cp source.txt destination.txt') 

# In Windows
os.popen('copy source.txt destination.txt')

os.systemChữ ký

os.system(command)


# In Linux/Unix
os.system('cp source.txt destination.txt')  

# In Windows
os.system('copy source.txt destination.txt')

3) Sao chép tệp bằng subprocess mô-đun

subprocess.callChữ ký

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True) 

# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)

subprocess.check_outputChữ ký

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)

# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)


20
2018-01-22 03:05





Bạn đã có thể sử dụng os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

hoặc như tôi đã làm,

os.system('cp '+ rawfile + ' rawdata.dat')

Ở đâu rawfile là tên mà tôi đã tạo ra bên trong chương trình.

Đây là giải pháp duy nhất của Linux


13
2017-12-19 23:18



đây không phải là di động, và không cần thiết vì bạn chỉ có thể sử dụng shutil. - Corey Goldberg
Ngay cả khi shutil không có sẵn - subprocess.run()(không có shell=True!) là giải pháp thay thế tốt hơn os.system(). - maxschlepzig


Đối với các tệp lớn, những gì tôi đã làm là đọc từng dòng tệp và đọc từng dòng vào một mảng. Sau đó, khi mảng đạt đến kích thước nhất định, hãy nối nó vào một tệp mới.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

8
2018-05-25 05:11



điều này có vẻ hơi dư thừa vì người viết nên xử lý bộ đệm. for l in open('file.txt','r'): output.write(l) nên tìm việc; chỉ cần thiết lập bộ đệm luồng đầu ra theo nhu cầu của bạn. hoặc bạn có thể đi qua các byte bằng cách lặp qua một thử với output.write(read(n)); output.flush() Ở đâu n là số byte bạn muốn viết tại một thời điểm. cả hai điều này cũng không có điều kiện để kiểm tra xem đó là phần thưởng. - owns
Có, nhưng tôi nghĩ rằng có lẽ điều này có thể dễ hiểu hơn vì nó sao chép toàn bộ các dòng thay vì một phần của chúng (trong trường hợp chúng ta không biết có bao nhiêu byte mỗi dòng). - ytpillai
Rất đúng. Mã hóa cho việc dạy và viết mã cho hiệu quả là rất khác nhau. - owns
@owns Để thêm vào câu hỏi này một năm sau đó, writelines() đã cho thấy hiệu suất tốt hơn một chút so với write() vì chúng tôi không lãng phí thời gian nhất quán khi mở một bộ phim mới, và thay vào đó, hãy viết những dòng mới là một phần lớn. - ytpillai
nhìn vào nguồn - writelines gọi write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c. Ngoài ra, luồng tệp đã được mở, do đó, viết sẽ không cần phải mở lại mỗi lần. - owns