Jalankan kode berikut dari direktori yang berisi direktori bernama bar
(mengandung satu atau lebih file) dan direktori bernama baz
(juga mengandung satu atau lebih file). Pastikan tidak ada direktori yang bernama foo
.
import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')
Itu akan gagal dengan:
$ python copytree_test.py
Traceback (most recent call last):
File "copytree_test.py", line 5, in <module>
shutil.copytree('baz', 'foo')
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'
Saya ingin ini bekerja dengan cara yang sama seperti jika saya telah mengetik:
$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/
Apakah saya perlu menggunakan shutil.copy()
untuk menyalin setiap file baz
ke dalam foo
? (Setelah saya sudah menyalin isi 'bar' ke 'foo' dengan shutil.copytree()
?) Atau apakah ada cara yang lebih mudah / lebih baik?
shutil.copytree()
perilaku untuk memungkinkan penulisan ke direktori yang ada, tetapi ada beberapa detail perilaku yang perlu disepakati.Jawaban:
Batasan standar ini
shutil.copytree
tampaknya sewenang-wenang dan menjengkelkan. Penanganan masalah:Perhatikan bahwa itu tidak sepenuhnya konsisten dengan standar
copytree
:symlinks
danignore
parameter untuk direktori root darisrc
pohon;shutil.Error
kesalahan di tingkat rootsrc
;shutil.Error
alih-alih mencoba menyalin subtree lain dan menaikkan satu kombinasishutil.Error
.sumber
shutil.copytree
tidakos.makedirs(dst)
di awal. Tidak ada bagian dari kode yang benar-benar memiliki masalah dengan direktori yang sudah ada sebelumnya. Ini perlu diubah. Setidaknya berikanexist_ok=False
parameter untuk panggilandef copyTree( src, dst, symlinks=False, ignore=None): for item in os.listdir(src): s = os.path.join(src, item) d = os.path.join(dst, item) if os.path.isdir(s): if os.path.isdir(d): self.recursiveCopyTree(s, d, symlinks, ignore) else: shutil.copytree(s, d, symlinks, ignore) else: shutil.copy2(s, d)
distutils.dir_util.copy_tree()
, yang juga berada di stdlib, tidak memiliki batasan seperti itu dan benar-benar berlaku seperti yang diharapkan. Karena itu, tidak ada alasan kuat untuk mencoba membuka gulungan implementasi Anda ( ... biasanya rusak ). Brendan Abel 's jawabannya harus benar-benar menjadi solusi yang diterima sekarang.Inilah solusi yang merupakan bagian dari pustaka standar:
Lihat pertanyaan serupa ini.
Salin konten direktori ke direktori dengan python
sumber
distutils.errors.DistutilsInternalError: mkpath: 'name' must be a string
, yaitu tidak menerimaPosixPath
. Perlu untukstr(PosixPath)
. Daftar keinginan untuk perbaikan. Selain masalah ini, saya lebih suka jawaban ini.Path
objek mewarisi daristr
saya kira, seperti kebanyakan implementasi sebelumnya dari objek path berorientasi objek ..distutils.dir_util.copy_tree()
dianggap sebagai detail implementasi distutils dan tidak direkomendasikan untuk penggunaan umum. Solusi nyata harus untukshutil.copytree()
ditingkatkan / diperluas untuk berperilaku lebih sepertidistutils.dir_util.copy_tree()
, tetapi tanpa kekurangannya. Sementara itu, saya akan terus menggunakan fungsi pembantu kustom mirip dengan beberapa yang disediakan dalam jawaban lain.Dalam sedikit perbaikan pada jawaban atzz untuk fungsi di mana fungsi di atas selalu mencoba untuk menyalin file dari sumber ke tujuan.
Dalam implementasi saya di atas
Saya menggunakan fungsi di atas bersama dengan membangun scon. Ini banyak membantu saya karena setiap kali saya mengkompilasi saya mungkin tidak perlu menyalin seluruh set file .. tetapi hanya file yang dimodifikasi.
sumber
if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:
Penggabungan yang terinspirasi oleh atzz dan Mital Vora:
sumber
[x for x in lst if x not in excl]
ini tidak melakukan hal yang sama dengan copytree, yang menggunakan pencocokan pola glob. en.wikipedia.org/wiki/Glob_(programming)Python 3.8 memperkenalkan
dirs_exist_ok
argumen untukshutil.copytree
:Oleh karena itu, dengan Python 3.8+ ini harus berfungsi:
sumber
dirs_exist_ok=False
secara default di copytree, tidak akankah upaya penyalinan pertama gagal?dirs_exist_ok
panggilan pertama untuk menggambarkan perbedaan (dan karena direktori belum ada dalam contoh OP), tetapi tentu saja Anda dapat menggunakannya jika Anda mau.dokumen secara eksplisit menyatakan bahwa direktori tujuan tidak boleh ada :
Saya pikir taruhan terbaik Anda adalah
os.walk
direktori kedua, semua direktori,copy2
dan file dan melakukan tambahancopystat
untuk direktori. Lagi pula itulah yangcopytree
dilakukan seperti yang dijelaskan dalam dokumen. Atau Anda bisacopy
dancopystat
setiap direktori / file danos.listdir
bukannyaos.walk
.sumber
Ini terinspirasi dari jawaban terbaik asli yang disediakan oleh atzz, saya baru saja menambahkan ganti logika file / folder. Jadi itu tidak benar-benar bergabung, tetapi menghapus file / folder yang ada dan menyalin yang baru:
Batalkan komentar rmtree untuk menjadikannya fungsi pemindahan.
sumber
Ini adalah versi saya dari tugas yang sama ::
sumber
Berikut adalah versi yang terinspirasi oleh utas ini yang lebih mirip meniru
distutils.file_util.copy_file
.updateonly
adalah bool jika True, hanya akan menyalin file dengan tanggal modifikasi yang lebih baru dari file yang adadst
kecuali terdaftar diforceupdate
mana akan menyalin.ignore
danforceupdate
mengharapkan daftar nama file atau folder / nama file relatif terhadapsrc
dan menerima wildcard gaya Unix mirip denganglob
ataufnmatch
.Fungsi mengembalikan daftar file yang disalin (atau akan disalin jika
dryrun
jika Benar).sumber
Solusi sebelumnya memiliki beberapa masalah yang
src
dapat ditimpadst
tanpa pemberitahuan atau pengecualian.Saya menambahkan
predict_error
metode untuk memprediksi kesalahan sebelum menyalin.copytree
terutama didasarkan pada versi Cyrille Pontvieux.Menggunakan
predict_error
untuk memprediksi semua kesalahan pada awalnya adalah yang terbaik, kecuali jika Anda ingin melihat pengecualian dimunculkan satu demi satu saat dijalankancopytree
hingga memperbaiki semua kesalahan.sumber
Ini kartu saya di masalahnya. Saya memodifikasi kode sumber untuk copytree untuk menjaga fungsi asli, tetapi sekarang tidak ada kesalahan terjadi ketika direktori sudah ada. Saya juga mengubahnya sehingga tidak menimpa file yang sudah ada tetapi menyimpan kedua salinan, satu dengan nama yang dimodifikasi, karena ini penting untuk aplikasi saya.
sumber
Coba ini:
sumber
Ini adalah versi yang mengharapkan
pathlib.Path
input sebagai.Perhatikan bahwa fungsi ini memerlukan Python 3.6, yang merupakan versi Python pertama di mana
os.listdir()
mendukung objek path-like sebagai input. Jika Anda perlu mendukung versi Python sebelumnya, Anda bisa menggantinyalistdir(src)
denganlistdir(str(src))
.sumber
saya akan menganggap cara tercepat dan termudah adalah memanggil python perintah sistem ...
contoh..
Tar dan gzip direktori .... unzip dan untar direktori di tempat yang diinginkan.
yah
sumber