كيف يمكنني نسخ ملف في بايثون؟
-
02-07-2019 - |
سؤال
كيف يمكنني نسخ ملف في بايثون؟
لم أتمكن من العثور على أي شيء تحت os
.
المحلول
shutil
لديه العديد من الطرق التي يمكنك استخدامها.واحد منها هو:
from shutil import copyfile
copyfile(src, dst)
انسخ محتويات الملف المسمى src
إلى ملف اسمه dst
.يجب أن يكون موقع الوجهة قابلاً للكتابة؛خلاف ذلك، أ IOError
سيتم رفع الاستثناء.لو dst
موجود بالفعل، سيتم استبداله.لا يمكن نسخ الملفات الخاصة مثل أجهزة الأحرف أو الكتل والأنابيب باستخدام هذه الوظيفة. src
و dst
هي أسماء المسارات المعطاة كسلاسل.
نصائح أخرى
┌──────────────────┬───────────────┬──────────────────┬──────────────┬───────────┐
│ 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 │
└──────────────────┴───────────────┴──────────────────┴──────────────┴───────────┘
copy2(src,dst)
غالبا ما يكون أكثر فائدة من copyfile(src,dst)
لأن:
- تسمح
dst
ليكون الدليل (بدلاً من اسم الملف الهدف الكامل)، وفي هذه الحالة سيتم الاسم الأساسي لsrc
يستخدم لإنشاء الملف الجديد. - فهو يحتفظ بالتعديل الأصلي ومعلومات الوصول (mtime وatime) في البيانات الوصفية للملف (ومع ذلك، يأتي هذا مع زيادة طفيفة).
هنا مثال قصير:
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
يمكنك استخدام إحدى وظائف النسخ من shutil
طَرد:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Function preserves supports accepts copies other permissions directory dest. file obj metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― Shutil.copy ✔ ✔ ☐ ☐ Shutil.copy2 ✔ ✔ ☐ ✔ Shutil.copyfile ☐ ☐ ☐ ☐ Shutil.copyfileobj ☐ ☐ ✔ ☐ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
مثال:
import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
يعد نسخ ملف عملية واضحة نسبيًا كما هو موضح في الأمثلة أدناه، ولكن يجب عليك بدلاً من ذلك استخدام الملف وحدة 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
وحدةos
وحدةsubprocess
وحدة
import os
import shutil
import subprocess
1) نسخ الملفات باستخدام 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)
2) نسخ الملفات باستخدام 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')
3) نسخ الملفات باستخدام 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)
استخدم ال وحدة Shutil.
copyfile(src, dst)
انسخ محتويات الملف المسمى src إلى ملف اسمه dst.يجب أن يكون موقع الوجهة قابلاً للكتابة؛وإلا، سيتم رفع استثناء IOError.إذا كان التوقيت الصيفي موجودًا بالفعل، فسيتم استبداله.لا يمكن نسخ الملفات الخاصة مثل أجهزة الأحرف أو الكتل والأنابيب باستخدام هذه الوظيفة.src وdst هما أسماء المسارات المعطاة كسلاسل.
نلقي نظرة على نظام الملفات لجميع وظائف معالجة الملفات والدليل المتوفرة في وحدات Python القياسية.
مثال على نسخة الدليل والملف - من Tim Golden's Python Stuff:
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"
يمكنك استخدام os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
أو كما فعلت
os.system('cp '+ rawfile + ' rawdata.dat')
أين rawfile
هو الاسم الذي قمت بإنشائه داخل البرنامج.
هذا هو الحل الوحيد لنظام Linux
بالنسبة للملفات الصغيرة واستخدام مكونات python المدمجة فقط، يمكنك استخدام السطر الواحد التالي:
with open(source, 'r') as src, open(dest, 'w') as dst: dst.write(src.read())
كما ذكر @maxschlepzig في التعليقات أدناه، هذه ليست الطريقة المثلى للتطبيقات التي يكون فيها الملف كبيرًا جدًا أو عندما تكون الذاكرة حرجة، وبالتالي سواتي ينبغي تفضيل الإجابة.
أولاً، قمت بإعداد ورقة غش شاملة لطرق 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',]
}
ثانياً: شرح طرق النسخ بالأمثلة:
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()``
نسخ شجرة الدليل بأكملها بشكل متكرر متجذرة في src، وإرجاع الدليل الوجهة
بالنسبة للملفات الكبيرة، ما فعلته هو قراءة الملف سطرًا تلو الآخر وقراءة كل سطر في مصفوفة.وبعد ذلك، بمجرد وصول المصفوفة إلى حجم معين، قم بإلحاقها بملف جديد.
for line in open("file.txt", "r"):
list.append(line)
if len(list) == 1000000:
output.writelines(list)
del list[:]
from subprocess import call
call("cp -p <file> <file>", shell=True)
اعتبارا من بايثون 3.5 يمكنك القيام بما يلي للملفات الصغيرة (على سبيل المثال:ملفات نصية، ملفات jpeg صغيرة):
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
سوف يحل محل كل ما كان في موقع الوجهة
open(destination, 'wb').write(open(source, 'rb').read())
افتح الملف المصدر في وضع القراءة، واكتب إلى الملف الوجهة في وضع الكتابة.
توفر Python وظائف مدمجة لنسخ الملفات بسهولة باستخدام الأدوات المساعدة لنظام التشغيل Shell.
يتم استخدام الأمر التالي لنسخ الملف
shutil.copy(src,dst)
يتم استخدام الأمر التالي لنسخ الملف باستخدام معلومات البيانات الوصفية
shutil.copystat(src,dst)