ฉันจะคัดลอกไฟล์ใน Python ได้อย่างไร
os
ฉันไม่สามารถหาอะไรภายใต้
ฉันจะคัดลอกไฟล์ใน Python ได้อย่างไร
os
ฉันไม่สามารถหาอะไรภายใต้
คำตอบ:
shutil
มีวิธีการมากมายที่คุณสามารถใช้ได้ หนึ่งในนั้นคือ:
from shutil import copyfile
copyfile(src, dst)
ถ้าคุณใช้os.path
การดำเนินงานการใช้งานมากกว่าcopy
จะยอมรับเฉพาะสตริงcopyfile
copyfile
~
แต่มันสามารถจัดการกับเส้นทางญาติ
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│ Function │ Copies │ Copies │Can use│ Destination │
│ │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy │ No │ Yes │ No │ Yes │
│shutil.copyfile │ No │ No │ No │ No │
│shutil.copy2 │ Yes │ Yes │ No │ Yes │
│shutil.copyfileobj│ No │ No │ Yes │ No │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
copy2(src,dst)
มักจะมีประโยชน์มากกว่าcopyfile(src,dst)
เพราะ:
dst
ให้เป็นไดเรกทอรี (แทนชื่อไฟล์เป้าหมายสมบูรณ์) ซึ่งในกรณีที่basenameของsrc
ใช้สำหรับการสร้างไฟล์ใหม่;นี่เป็นตัวอย่างสั้น ๆ :
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
copyfile
เร็วกว่ามากcopy2
shutil.copy2('/dir/file.ext', '/new/dir/')
(ที่มีเครื่องหมายสแลชหลังพา ธ เป้าหมาย) จะลบความกำกวมว่าจะคัดลอกไปยังไฟล์ใหม่ที่เรียกว่า "dir" หรือเพื่อวางไฟล์ลงในไดเรกทอรีของชื่อนั้นหรือไม่?
/new/dir
เป็นไดเรกทอรีที่มีอยู่ให้ดูความคิดเห็นของ @ MatthewAlpert
/new/dir/
ไม่มีอยู่ Python จะทำการโยนIsADirectoryError
มิฉะนั้นจะทำการคัดลอกไฟล์ไปยัง/new/dir/
ชื่อเดิม
คุณสามารถใช้หนึ่งในฟังก์ชั่นการคัดลอกจากshutil
แพ็คเกจ:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ฟังก์ชั่นเก็บรักษารองรับการยอมรับสำเนาอื่น ๆ ปลายทางไดเรกทอรีสิทธิ์ ไฟล์ obj metadata -------------------------------------------------- ---------------------------- shutil.copy ✔✔☐☐ shutil.copy2 ✔✔☐✔ shutil.copyfile ☐☐☐☐ shutil.copyfileobj ☐☐✔☐ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ตัวอย่าง:
import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
ใน Python คุณสามารถคัดลอกไฟล์โดยใช้
shutil
โมดูลos
โมดูลsubprocess
โมดูลimport os
import shutil
import subprocess
shutil
โมดูลshutil.copyfile
ลายเซ็น
shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copyfile('source.txt', 'destination.txt')
shutil.copy
ลายเซ็น
shutil.copy(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy('source.txt', 'destination.txt')
shutil.copy2
ลายเซ็น
shutil.copy2(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy2('source.txt', 'destination.txt')
shutil.copyfileobj
ลายเซ็น
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)
os
โมดูลos.popen
ลายเซ็น
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.system
ลายเซ็น
os.system(command)
# In Linux/Unix
os.system('cp source.txt destination.txt')
# In Windows
os.system('copy source.txt destination.txt')
subprocess
โมดูลsubprocess.call
ลายเซ็น
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_output
ลายเซ็น
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)
['copy', sourcefile, destfile]
ไวยากรณ์เมื่อใดก็ตามที่เป็นไปได้โดยเฉพาะถ้าพารามิเตอร์มาจากการป้อนข้อมูลของผู้ใช้
os.popen
เลิกใช้ไประยะหนึ่งแล้ว และcheck_output
ไม่ส่งคืนสถานะ แต่เอาต์พุต (ซึ่งว่างเปล่าในกรณีของcopy/cp
)
การคัดลอกไฟล์เป็นการดำเนินการที่ค่อนข้างตรงไปตรงมาตามที่แสดงโดยตัวอย่างด้านล่าง แต่คุณควรใช้โมดูล shutil stdlibแทน
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)
หากคุณต้องการคัดลอกชื่อไฟล์คุณสามารถทำสิ่งนี้:
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)
shutil.copyfileobj
ใช่ผมไม่แน่ใจว่าทำไมคุณจะไม่ได้เป็นเพียงคัดลอกแหล่งที่มาของ นอกจากนี้คุณไม่จำเป็นต้องtry, finally
จัดการกับการปิดไฟล์หลังจากข้อยกเว้น ฉันจะบอกว่าฟังก์ชั่นของคุณไม่ควรรับผิดชอบในการเปิดและปิดไฟล์เลย ว่าควรจะไปในฟังก์ชั่นเสื้อคลุมเช่นวิธีการตัดshutil.copyfile
shutil.copyfileobj
dest
สามารถเขียนได้:open(dest, 'wb')
ใช้โมดูล shutil
copyfile(src, dst)
คัดลอกเนื้อหาของไฟล์ชื่อ src ไปยังไฟล์ชื่อ dst ตำแหน่งปลายทางต้องสามารถเขียนได้ มิฉะนั้นจะเกิดข้อยกเว้น IOError หาก dst มีอยู่แล้วจะถูกแทนที่ ไฟล์พิเศษเช่นอุปกรณ์ตัวละครหรือบล็อกและท่อไม่สามารถคัดลอกด้วยฟังก์ชั่นนี้ src และ dst เป็นชื่อพา ธ ที่กำหนดเป็นสตริง
ดูfilesysสำหรับฟังก์ชั่นการจัดการไฟล์และไดเรกทอรีทั้งหมดที่มีอยู่ในโมดูล Python มาตรฐาน
ตัวอย่างการคัดลอกไดเรกทอรีและไฟล์ - จากรายการ Python ของ 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"
ประการแรกฉันทำสูตร cheatsheet ครบถ้วนของวิธีการ shutil สำหรับการอ้างอิงของคุณ
shutil_methods =
{'copy':['shutil.copyfileobj',
'shutil.copyfile',
'shutil.copymode',
'shutil.copystat',
'shutil.copy',
'shutil.copy2',
'shutil.copytree',],
'move':['shutil.rmtree',
'shutil.move',],
'exception': ['exception shutil.SameFileError',
'exception shutil.Error'],
'others':['shutil.disk_usage',
'shutil.chown',
'shutil.which',
'shutil.ignore_patterns',]
}
ประการที่สองอธิบายวิธีการคัดลอกใน exmaples:
shutil.copyfileobj(fsrc, fdst[, length])
จัดการกับวัตถุที่เปิดอยู่
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
...: shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
shutil.copyfile(src, dst, *, follow_symlinks=True)
คัดลอกและเปลี่ยนชื่อ
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
shutil.copy()
คัดลอกโดยไม่ต้องเก็บเมตาดาต้าไว้ล่วงหน้า
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
shutil.copy2()
คัดลอกด้วยการกำหนดข้อมูลเมตาล่วงหน้า
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
shutil.copytree()
คัดลอกทรีไดเรกทอรีทั้งหมดซ้ำ ๆ ที่ root ที่ src ส่งคืนไดเร็กทอรีปลายทาง
สำหรับไฟล์ขนาดเล็กและใช้ python ในตัวเท่านั้นคุณสามารถใช้หนึ่งบรรทัดต่อไปนี้:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
ตามที่ @maxschlepzig ได้กล่าวถึงในความคิดเห็นด้านล่างนี่ไม่ใช่วิธีที่ดีที่สุดสำหรับแอปพลิเคชันที่ไฟล์มีขนาดใหญ่เกินไปหรือเมื่อหน่วยความจำมีความสำคัญดังนั้นจึงควรเลือกคำตอบของ Swati
.read()
และ.write()
บัฟเฟอร์ตามค่าเริ่มต้น (อย่างน้อยสำหรับ CPython)
open()
บัฟเฟอร์ IO โดยค่าเริ่มต้นไม่ได้ช่วยให้คุณที่นี่เพราะread()
มีการระบุเป็น: 'ถ้า n เป็นลบหรือละเว้นให้อ่านจนกว่า EOF' นั่นหมายความว่าการread()
ส่งคืนเนื้อหาไฟล์ทั้งหมดเป็นสตริง
คุณสามารถใช้ os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
หรืออย่างที่ฉันทำ
os.system('cp '+ rawfile + ' rawdata.dat')
ซึ่งrawfile
เป็นชื่อที่ผมสร้างขึ้นภายในโปรแกรม
นี่เป็นโซลูชัน Linux เท่านั้น
shutil
ไม่สามารถใช้ได้ - subprocess.run()
(ไม่shell=True
) os.system()
เป็นทางเลือกที่ดีกว่าที่จะ
subprocess.run()
ตามที่แนะนำโดย @maxschlepzig เป็นขั้นตอนใหญ่ข้างหน้าเมื่อเรียกโปรแกรมภายนอก เพื่อความยืดหยุ่นและความปลอดภัยให้ใช้['cp', rawfile, 'rawdata.dat']
รูปแบบการส่งผ่านบรรทัดคำสั่ง (อย่างไรก็ตามสำหรับการคัดลอกshutil
และเพื่อน ๆ ขอแนะนำให้เรียกโปรแกรมภายนอก)
สำหรับไฟล์ขนาดใหญ่สิ่งที่ฉันทำคืออ่านไฟล์ทีละบรรทัดและอ่านแต่ละบรรทัดในอาเรย์ จากนั้นเมื่ออาร์เรย์ถึงขนาดที่กำหนดแล้วให้ผนวกกับไฟล์ใหม่
for line in open("file.txt", "r"):
list.append(line)
if len(list) == 1000000:
output.writelines(list)
del list[:]
for l in open('file.txt','r'): output.write(l)
ควรทำงานหา; เพียงติดตั้งบัฟเฟอร์กระแสเอาต์พุตตามความต้องการของคุณ หรือคุณสามารถไปโดยไบต์โดยการวนลูปลองกับoutput.write(read(n)); output.flush()
ที่n
เป็นจำนวนไบต์ที่คุณต้องการที่จะเขียนในเวลา ทั้งสองอย่างนี้ไม่มีเงื่อนไขในการตรวจสอบว่าเป็นโบนัสอะไร
shutil
? แม้เมื่อเพิกเฉยshutil
การอ่าน / เขียนลูปแบบง่าย ๆ บล็อก (ใช้ IO ที่ไม่มีบัฟเฟอร์) อยู่ข้างหน้าจะมีประสิทธิภาพและจะทำให้มีความรู้สึกมากกว่านี้และทำให้ง่ายต่อการสอนและเข้าใจ
from subprocess import call
call("cp -p <file> <file>", shell=True)
call
นี้ไม่ปลอดภัย กรุณาอ้างอิงถึงโปรแกรมย่อย docu เกี่ยวกับเรื่องนี้
ในPython 3.5คุณสามารถทำสิ่งต่อไปนี้สำหรับไฟล์ขนาดเล็ก (เช่น: ไฟล์ข้อความ, jpegs ขนาดเล็ก):
from pathlib import Path
source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())
write_bytes
จะเขียนทับสิ่งที่เป็นที่ตั้งของปลายทาง
shutil
จัดการกับกรณีพิเศษทั้งหมดสำหรับคุณและให้ความอุ่นใจ
open(destination, 'wb').write(open(source, 'rb').read())
เปิดไฟล์ต้นฉบับในโหมดอ่านและเขียนไปยังไฟล์ปลายทางในโหมดเขียน
.close()
ทั้งหมดopen(...)
หรือไม่
Python มีฟังก์ชั่นที่สร้างขึ้นเพื่อการคัดลอกไฟล์อย่างง่ายดายโดยใช้ยูทิลิตี้เชลล์ระบบปฏิบัติการ
คำสั่งดังต่อไปนี้จะใช้ในการคัดลอกไฟล์
shutil.copy(src,dst)
คำสั่งต่อไปนี้ใช้เพื่อคัดลอกไฟล์ด้วยข้อมูล MetaData
shutil.copystat(src,dst)
copy
จากนั้นcopystat
เก็บไฟล์ข้อมูลเมตา ใน Python 3.3+ copystat
ก็อปปี้แอ็ตทริบิวต์ส่วนขยาย