سؤال

كيف يمكنني نسخ ملف في بايثون؟

لم أتمكن من العثور على أي شيء تحت 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)

في بايثون، يمكنك نسخ الملفات باستخدام


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',]
}

ثانياً: شرح طرق النسخ بالأمثلة:

  1. 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)
  1. 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
  1. 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
  1. 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
  1. `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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top