Perhatikan bahwa tidak semua metadata akan disalin, tergantung pada platform Anda.
Kevin Horn
12
Perhatikan bahwa ini bukan operasi atom. Berhati-hatilah menggunakannya dalam aplikasi berulir.
waterbyte
4
Perhatikan bahwa itu tidak bisa menangani singkatan seperti ~, tetapi dapat menangani jalur relatif
zwep
1253
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│ 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 │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
Saya mencoba menyalin secara acak 100 ribu file dari 1 juta file. copyfilejauh lebih cepat daripadacopy2
Vijay
4
apakah saya benar untuk menganggap bahwa shutil.copy2('/dir/file.ext', '/new/dir/')(dengan garis miring setelah jalur target) akan menghapus ambiguitas mengenai apakah akan menyalin ke file baru yang disebut "dir" atau untuk memasukkan file ke direktori nama itu?
Zak
1
@ Vijay, saya yakin overhead ini karena menyalin metadata.
Jonathan H
@ Zak Tidak ada ambiguitas jika /new/dirada direktori yang ada, lihat komentar @ MatthewAlpert.
Jonathan H
@ Zak Anda benar, menambahkan garis miring pada akhirnya menghilangkan ambiguitas. Jika /new/dir/tidak ada, Python akan melempar IsADirectoryError, jika tidak, menyalin file ke /new/dir/bawah nama asli.
martonbognar
125
Anda dapat menggunakan salah satu fungsi salin dari shutilpaket:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Fungsi mempertahankan mendukung menerima salinan lainnya
direktori hak akses. mengajukan keberatan metadata
―――――――――――――――――――――――――――――――――――――――――――――――――― ――――――――――――――――――――――――――――
shutil.copy ✔ ✔ ☐ ☐
shutil.copy2 ✔ ✔ ☐ ✔
shutil.copyfile ☐ ☐ ☐ ☐
shutil.copyfileobj ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Hanya ingin tahu, bagaimana Anda menghasilkan tabel itu?
lightalchemist
16
@lightalchemist Saya baru saja menggunakan vim sebagai scratchpad, menyalin simbol unicode yang digunakan dari tabel wikipedia dan menyalin hasilnya ke editor stackoverflow untuk pemolesan akhir.
@wim, Anda harus membandingkan jawaban saya dengan versi 2017 dari jawaban yang Anda tautkan saat ini ketika saya memposting jawaban saya. Perbedaan utama: jawaban saya menggunakan tajuk kolom yang lebih baik / lebih deskriptif, tata letak tabel tidak mengganggu, itu termasuk tautan langsung ke dalam dokumentasi dan saya menambahkan kolom (yaitu 'menerima file obj').
maxschlepzig
4
BAIK. YMMV, tapi saya pikir perubahan kosmetik dan perbaikan kecil seperti itu lebih baik dilakukan sebagai pengeditan pada jawaban yang ada, daripada duplikasi jawaban.
wim
104
Dengan Python, Anda dapat menyalin file menggunakan
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')
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(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)
Menggunakan perintah single-string adalah gaya pengkodean yang buruk (fleksibilitas, keandalan dan keamanan), alih-alih menggunakan ['copy', sourcefile, destfile]sintaksis sedapat mungkin, terutama jika parameternya dari input pengguna.
Marcel Waldvogel
8
Mengapa Anda daftar begitu banyak alternatif buruk untuk fungsi salin shutil?
maxschlepzig
6
shutil built-in, tidak perlu menyediakan alternatif non-portabel. Jawabannya dapat benar-benar ditingkatkan dengan menghapus solusi yang bergantung pada sistem, dan setelah penghapusan itu, jawaban ini hanyalah salinan dari jawaban yang ada / salinan dokumentasi.
Jean-François Fabre
3
os.popensudah ditinggalkan untuk sementara waktu sekarang. dan check_outputtidak mengembalikan status tetapi output (yang kosong dalam kasus copy/cp)
Jean-François Fabre
2
shutil sebenarnya tidak menyalin file. Ada peringatan besar di bagian atas dokumen . "Ini berarti pemilik file dan grup hilang serta ACL. Pada Mac OS, garpu sumber daya dan metadata lainnya tidak digunakan. Ini berarti bahwa sumber daya akan hilang dan jenis file dan kode pembuat tidak akan benar. Pada Windows, pemilik file, ACL, dan aliran data alternatif tidak disalin. "
GM
96
Menyalin file adalah operasi yang relatif mudah seperti yang ditunjukkan oleh contoh di bawah ini, tetapi Anda sebaiknya menggunakan modul shutil stdlib untuk itu.
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.
"""whileTrue:
copy_buffer = source.read(buffer_size)ifnot copy_buffer:break
dest.write(copy_buffer)
Jika Anda ingin menyalin dengan nama file Anda bisa melakukan sesuatu seperti ini:
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)
Saya melihat beberapa waktu lalu bahwa modul disebut shutil (tunggal) dan tidak shutils (jamak), dan memang itu adalah Python 2.3. Namun demikian saya meninggalkan fungsi ini di sini sebagai contoh.
pi.
4
Menyalin isi file adalah operasi yang mudah. Menyalin file dengan metadata-nya sama sekali tidak langsung, terlebih lagi jika Anda ingin cross-platform.
LaC
3
Benar. Melihat dokumen shutil, fungsi copyfile juga tidak akan menyalin metadata.
pi.
3
Ya, saya tidak yakin mengapa Anda tidak hanya menyalin sumber shutil.copyfileobj. Selain itu, Anda tidak perlu try, finallymenangani penutupan file setelah pengecualian. Saya akan mengatakan, bahwa fungsi Anda seharusnya tidak bertanggung jawab untuk membuka dan menutup file sama sekali. Itu harus masuk dalam fungsi pembungkus, seperti bagaimana shutil.copyfilemembungkus shutil.copyfileobj.
ErlVolton
2
Kode di atas harus menentukan destdapat ditulisi:open(dest, 'wb')
Salin konten file bernama src ke file bernama dst. Lokasi tujuan harus dapat ditulis; jika tidak, pengecualian IOError akan dimunculkan. Jika dst sudah ada, itu akan diganti. File khusus seperti karakter atau perangkat blok dan pipa tidak dapat disalin dengan fungsi ini. src dan dst adalah nama path yang diberikan sebagai string.
Lihatlah filesys untuk semua fungsi penanganan file dan direktori yang tersedia dalam modul Python standar.
shutil sebenarnya tidak menyalin file. Ada peringatan besar di bagian atas dokumen . "Ini berarti pemilik file dan grup hilang serta ACL. Pada Mac OS, garpu sumber daya dan metadata lainnya tidak digunakan. Ini berarti bahwa sumber daya akan hilang dan jenis file dan kode pembuat tidak akan benar. Pada Windows, pemilik file, ACL, dan aliran data alternatif tidak disalin. "
GM
47
Contoh Direktori dan Salin File - Dari Barang Python Tim Golden:
shutil sebenarnya tidak menyalin file. Ada peringatan besar di bagian atas dokumen . "Ini berarti pemilik file dan grup hilang serta ACL. Pada Mac OS, garpu sumber daya dan metadata lainnya tidak digunakan. Ini berarti bahwa sumber daya akan hilang dan jenis file dan kode pembuat tidak akan benar. Pada Windows, pemilik file, ACL, dan aliran data alternatif tidak disalin. "
GM
19
Untuk file kecil dan hanya menggunakan built-in python, Anda dapat menggunakan one-liner berikut:
with open(source,'rb')as src, open(dest,'wb')as dst: dst.write(src.read())
Seperti @maxschlepzig disebutkan dalam komentar di bawah, ini bukan cara yang optimal untuk aplikasi di mana file terlalu besar atau ketika memori kritis, sehingga jawaban Swati harus lebih disukai.
Ini membaca file sumber lengkap ke dalam memori sebelum menulis kembali. Dengan demikian, ini tidak perlu menghabiskan memori untuk semua kecuali operasi penyalinan file terkecil.
maxschlepzig
1
Benarkah? Saya pikir .read()dan .write()buffered secara default (setidaknya untuk CPython).
soundstripe
@soundstripe, Tentu saja ini benar. Fakta bahwa objek file yang dikembalikan oleh open()buffer IO, secara default tidak membantu Anda di sini, karena read()ditentukan sebagai: 'Jika n negatif atau dihilangkan, baca sampai EOF.' Itu berarti read()mengembalikan konten file lengkap sebagai string.
maxschlepzig
@maxschlepzig Saya mengerti maksud Anda dan saya akui saya tidak menyadarinya. Alasan saya memberikan jawaban ini adalah jika seseorang ingin melakukan salinan file sederhana hanya menggunakan built-in, tanpa perlu mengimpor modul untuk itu. Tentu saja pengoptimalan memori seharusnya tidak menjadi masalah jika Anda menginginkan opsi ini. Bagaimanapun terima kasih telah membersihkannya. Saya memperbarui jawabannya.
yellow01
14
Anda bisa menggunakannya os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
atau seperti yang saya lakukan,
os.system('cp '+ rawfile +' rawdata.dat')
di mana rawfilenama yang saya buat di dalam program.
ini tidak portabel, dan tidak perlu karena Anda bisa menggunakan shutil.
Corey Goldberg
4
Bahkan ketika shutiltidak tersedia - subprocess.run() (tanpa shell=True!) Adalah alternatif yang lebih baik os.system().
maxschlepzig
1
shutil lebih portabel
Hiadore
1
subprocess.run()seperti yang disarankan oleh @maxschlepzig adalah langkah besar ke depan, saat memanggil program eksternal. Namun untuk fleksibilitas dan keamanan, gunakan ['cp', rawfile, 'rawdata.dat']bentuk melewati baris perintah. (Namun, untuk menyalin, shutildan teman-teman disarankan untuk tidak memanggil program eksternal.)
Marcel Waldvogel
2
coba itu dengan nama file dengan spasi di dalamnya.
Jean-François Fabre
11
Untuk file besar, yang saya lakukan adalah membaca file baris demi baris dan membaca setiap baris menjadi sebuah array. Kemudian, setelah array mencapai ukuran tertentu, tambahkan ke file baru.
for line in open("file.txt","r"):
list.append(line)if len(list)==1000000:
output.writelines(list)del list[:]
ini sepertinya sedikit berlebihan karena penulis harus menangani buffering. for l in open('file.txt','r'): output.write(l)harus bekerja temukan; hanya mengatur buffer aliran output sesuai kebutuhan Anda. atau Anda dapat pergi dengan byte dengan mengulangi coba dengan di output.write(read(n)); output.flush()mana njumlah byte yang ingin Anda tulis sekaligus. keduanya juga tidak memiliki syarat untuk memeriksa mana yang merupakan bonus.
Memiliki
1
Ya, tapi saya pikir mungkin ini bisa lebih mudah dimengerti karena menyalin seluruh baris daripada bagian-bagiannya (kalau-kalau kita tidak tahu berapa byte setiap baris).
ytpillai
Sangat benar. Pengkodean untuk pengajaran dan pengkodean untuk efisiensi sangat berbeda.
Ini mengerikan. Itu bekerja tidak perlu tanpa alasan yang bagus. Itu tidak berfungsi untuk file sewenang-wenang. Salinan tidak byte-identik jika input memiliki ujung garis yang tidak biasa pada sistem seperti Windows. Menurut Anda mengapa ini mungkin lebih mudah dipahami daripada panggilan ke fungsi salin shutil? Bahkan ketika mengabaikan shutil, loop blok baca / tulis sederhana (menggunakan IO unbuffered) langsung, akan efisien dan akan jauh lebih masuk akal daripada ini, dan dengan demikian tentu lebih mudah untuk diajarkan dan dipahami.
maxschlepzig
11
from subprocess import call
call("cp -p <file> <file>", shell=True)
Dan kemudian seseorang menggunakan kode (secara tidak sengaja atau sengaja) pada file besar ... Menggunakan fungsi dari shutilmenangani semua kasus khusus untuk Anda dan memberi Anda ketenangan pikiran.
Marcel Waldvogel
4
setidaknya itu tidak mengulangi solusi yang sama berulang-ulang.
Idenya bagus dan kodenya indah, tetapi fungsi salin () yang tepat dapat melakukan lebih banyak hal, seperti menyalin atribut (+ x bit), atau misalnya menghapus byte yang sudah disalin dalam kasus kondisi disk-penuh ditemukan .
Raúl Salinas-Monteagudo
1
Semua jawaban perlu penjelasan, meskipun hanya satu kalimat. Tidak ada penjelasan yang menetapkan preseden buruk dan tidak membantu dalam memahami program. Bagaimana jika noob Python lengkap datang dan melihat ini, ingin menggunakannya, tetapi tidak bisa karena mereka tidak memahaminya? Anda ingin membantu semua dalam jawaban Anda.
connectyourcharger
1
Bukankah itu melewatkan .close()semua open(...)itu?
luckydonald
Tidak perlu .close (), karena kita TIDAK MENYIMPAN objek penunjuk file di mana saja (baik untuk file src maupun untuk file tujuan).
Jawaban:
shutil
memiliki banyak metode yang dapat Anda gunakan. Salah satunya adalah:Jika Anda menggunakan
os.path
operasi, gunakancopy
daripadacopyfile
. hanyacopyfile
akan menerima string .sumber
~
, tetapi dapat menangani jalur relatifsumber
copy2(src,dst)
seringkali lebih bermanfaat daripadacopyfile(src,dst)
karena:dst
untuk menjadi direktori (bukan nama file target lengkap), dalam hal ini nama dasar darisrc
digunakan untuk membuat file baru;Ini adalah contoh singkat:
sumber
copyfile
jauh lebih cepat daripadacopy2
shutil.copy2('/dir/file.ext', '/new/dir/')
(dengan garis miring setelah jalur target) akan menghapus ambiguitas mengenai apakah akan menyalin ke file baru yang disebut "dir" atau untuk memasukkan file ke direktori nama itu?/new/dir
ada direktori yang ada, lihat komentar @ MatthewAlpert./new/dir/
tidak ada, Python akan melemparIsADirectoryError
, jika tidak, menyalin file ke/new/dir/
bawah nama asli.Anda dapat menggunakan salah satu fungsi salin dari
shutil
paket:Contoh:
sumber
Dengan Python, Anda dapat menyalin file menggunakan
shutil
modulos
modulsubprocess
modul1) Menyalin file menggunakan
shutil
modulshutil.copyfile
tanda tanganshutil.copy
tanda tanganshutil.copy2
tanda tanganshutil.copyfileobj
tanda tangan2) Menyalin file menggunakan
os
modulos.popen
tanda tanganos.system
tanda tangan3) Menyalin file menggunakan
subprocess
modulsubprocess.call
tanda tangansubprocess.check_output
tanda tangansumber
['copy', sourcefile, destfile]
sintaksis sedapat mungkin, terutama jika parameternya dari input pengguna.os.popen
sudah ditinggalkan untuk sementara waktu sekarang. dancheck_output
tidak mengembalikan status tetapi output (yang kosong dalam kasuscopy/cp
)Menyalin file adalah operasi yang relatif mudah seperti yang ditunjukkan oleh contoh di bawah ini, tetapi Anda sebaiknya menggunakan modul shutil stdlib untuk itu.
Jika Anda ingin menyalin dengan nama file Anda bisa melakukan sesuatu seperti ini:
sumber
shutil.copyfileobj
. Selain itu, Anda tidak perlutry, finally
menangani penutupan file setelah pengecualian. Saya akan mengatakan, bahwa fungsi Anda seharusnya tidak bertanggung jawab untuk membuka dan menutup file sama sekali. Itu harus masuk dalam fungsi pembungkus, seperti bagaimanashutil.copyfile
membungkusshutil.copyfileobj
.dest
dapat ditulisi:open(dest, 'wb')
Gunakan modul shutil .
Salin konten file bernama src ke file bernama dst. Lokasi tujuan harus dapat ditulis; jika tidak, pengecualian IOError akan dimunculkan. Jika dst sudah ada, itu akan diganti. File khusus seperti karakter atau perangkat blok dan pipa tidak dapat disalin dengan fungsi ini. src dan dst adalah nama path yang diberikan sebagai string.
Lihatlah filesys untuk semua fungsi penanganan file dan direktori yang tersedia dalam modul Python standar.
sumber
Contoh Direktori dan Salin File - Dari Barang Python Tim Golden:
http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html
sumber
Pertama, saya membuat cheatsheet lengkap tentang metode shutil untuk referensi Anda.
Kedua, jelaskan metode penyalinan dalam exmaples:
Secara rekursif menyalin seluruh pohon direktori yang di-root di src, mengembalikan direktori tujuan
sumber
Untuk file kecil dan hanya menggunakan built-in python, Anda dapat menggunakan one-liner berikut:
Seperti @maxschlepzig disebutkan dalam komentar di bawah, ini bukan cara yang optimal untuk aplikasi di mana file terlalu besar atau ketika memori kritis, sehingga jawaban Swati harus lebih disukai.
sumber
.read()
dan.write()
buffered secara default (setidaknya untuk CPython).open()
buffer IO, secara default tidak membantu Anda di sini, karenaread()
ditentukan sebagai: 'Jika n negatif atau dihilangkan, baca sampai EOF.' Itu berartiread()
mengembalikan konten file lengkap sebagai string.Anda bisa menggunakannya
os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
atau seperti yang saya lakukan,
di mana
rawfile
nama yang saya buat di dalam program.Ini adalah solusi hanya Linux
sumber
shutil
tidak tersedia -subprocess.run()
(tanpashell=True
!) Adalah alternatif yang lebih baikos.system()
.subprocess.run()
seperti yang disarankan oleh @maxschlepzig adalah langkah besar ke depan, saat memanggil program eksternal. Namun untuk fleksibilitas dan keamanan, gunakan['cp', rawfile, 'rawdata.dat']
bentuk melewati baris perintah. (Namun, untuk menyalin,shutil
dan teman-teman disarankan untuk tidak memanggil program eksternal.)Untuk file besar, yang saya lakukan adalah membaca file baris demi baris dan membaca setiap baris menjadi sebuah array. Kemudian, setelah array mencapai ukuran tertentu, tambahkan ke file baru.
sumber
for l in open('file.txt','r'): output.write(l)
harus bekerja temukan; hanya mengatur buffer aliran output sesuai kebutuhan Anda. atau Anda dapat pergi dengan byte dengan mengulangi coba dengan dioutput.write(read(n)); output.flush()
manan
jumlah byte yang ingin Anda tulis sekaligus. keduanya juga tidak memiliki syarat untuk memeriksa mana yang merupakan bonus.shutil
? Bahkan ketika mengabaikanshutil
, loop blok baca / tulis sederhana (menggunakan IO unbuffered) langsung, akan efisien dan akan jauh lebih masuk akal daripada ini, dan dengan demikian tentu lebih mudah untuk diajarkan dan dipahami.sumber
call
itu tidak aman. Silakan merujuk pada dokumen subproses tentang hal itu.Pada Python 3.5 Anda dapat melakukan hal berikut untuk file kecil (yaitu: file teks, jpeg kecil):
write_bytes
akan menimpa apa pun yang ada di lokasi tujuansumber
shutil
menangani semua kasus khusus untuk Anda dan memberi Anda ketenangan pikiran.Buka file sumber dalam mode baca, dan tulis ke file tujuan dalam mode tulis.
sumber
.close()
semuaopen(...)
itu?Python menyediakan fungsi bawaan untuk menyalin file dengan mudah menggunakan utilitas Shell Sistem Pengoperasian.
Perintah berikut digunakan untuk menyalin file
Perintah berikut digunakan untuk menyalin file dengan informasi MetaData
sumber
copy
kemudiancopystat
untuk melestarikan file metadata. Dalam Python 3.3+copystat
juga menyalin atribut yang diperluas.