Saya diuji cp
dengan perintah berikut:
$ ls
first.html second.html third.html
$ cat first.html
first
$ cat second.html
second
$ cat third.html
third
Lalu saya salin first.html
ke second.html
:
$ cp first.html second.html
$ cat second.html
first
File second.html
ditimpa secara diam-diam tanpa kesalahan. Namun, jika saya melakukannya di GUI desktop dengan menyeret dan menjatuhkan file dengan nama yang sama, itu akan berakhiran first1.html
secara otomatis. Ini menghindari menimpa file yang ada secara tidak sengaja.
Mengapa tidak cp
mengikuti pola ini alih-alih menimpa file secara diam-diam?
cp
untukcp -i
atau serupa karena Anda akan terbiasa untuk memiliki jaring pengaman, membuat sistem di mana itu tidak tersedia (sebagian besar dari mereka) yang jauh lebih berisiko. Lebih baik mengajari diri sendiri untuk secara rutincp -i
dll jika itu yang Anda inginkan.Jawaban:
Perilaku overwrite default
cp
ditentukan dalam POSIX.Ketika spesifikasi POSIX ditulis, sudah ada sejumlah besar skrip yang ada, dengan asumsi bawaan untuk perilaku overwrite default. Banyak dari skrip tersebut dirancang untuk dijalankan tanpa kehadiran pengguna langsung, misalnya sebagai tugas cron atau tugas latar belakang lainnya. Mengubah perilaku akan menghancurkan mereka. Meninjau dan memodifikasi mereka semua untuk menambahkan opsi untuk memaksa menimpa di mana pun dibutuhkan mungkin dianggap sebagai tugas besar dengan manfaat minimal.
Juga, baris perintah Unix selalu dirancang untuk memungkinkan pengguna yang berpengalaman untuk bekerja secara efisien, bahkan dengan mengorbankan kurva belajar yang sulit bagi seorang pemula. Ketika pengguna memasukkan perintah, komputer berharap bahwa pengguna benar-benar bersungguh-sungguh, tanpa menebak-nebak; itu adalah tanggung jawab pengguna untuk berhati-hati dengan perintah yang berpotensi merusak.
Ketika Unix asli dikembangkan, sistem kemudian memiliki memori dan penyimpanan massal yang sangat sedikit dibandingkan dengan komputer modern yang menimpa peringatan dan prompt yang mungkin dianggap sebagai kemewahan yang sia-sia dan tidak perlu.
Ketika standar POSIX sedang ditulis, preseden dibuat dengan mantap, dan para penulis dari standar tersebut menyadari dengan baik sifat-sifat tidak merusak kompatibilitas ke belakang .
Selain itu, seperti yang telah dijelaskan orang lain, setiap pengguna dapat menambah / mengaktifkan fitur-fitur itu untuk diri mereka sendiri, dengan menggunakan alias shell atau bahkan dengan membangun
cp
perintah penggantian dan memodifikasi mereka$PATH
untuk menemukan penggantian sebelum perintah sistem standar, dan mendapatkan jaring pengaman seperti itu jika diinginkan.Tetapi jika Anda melakukannya, Anda akan menemukan bahwa Anda menciptakan bahaya untuk diri Anda sendiri. Jika
cp
perintah berperilaku satu cara ketika digunakan secara interaktif dan cara lain ketika dipanggil dari skrip, Anda mungkin tidak ingat bahwa ada perbedaan. Di sistem lain, Anda mungkin ceroboh karena terbiasa dengan peringatan dan permintaan di sistem Anda sendiri.Jika perilaku dalam skrip masih akan cocok dengan standar POSIX, Anda cenderung terbiasa dengan permintaan dalam penggunaan interaktif, kemudian menulis skrip yang melakukan beberapa penyalinan massal - dan kemudian menemukan Anda sekali lagi secara tidak sengaja menimpa sesuatu.
Jika Anda menerapkan skrip juga, apa yang akan dilakukan perintah ketika dijalankan dalam konteks yang tidak memiliki pengguna, misalnya proses latar belakang atau tugas cron? Apakah skrip akan hang, batalkan, atau ditimpa?
Menggantung atau menggugurkan berarti bahwa tugas yang seharusnya dilakukan secara otomatis tidak akan dilakukan. Tidak menimpa kadang-kadang juga dapat menyebabkan masalah dengan sendirinya: misalnya, dapat menyebabkan data lama diproses dua kali oleh sistem lain alih-alih diganti dengan data terbaru.
Sebagian besar kekuatan baris perintah berasal dari kenyataan bahwa setelah Anda tahu cara melakukan sesuatu di baris perintah, Anda secara implisit juga akan tahu bagaimana mewujudkannya secara otomatis dengan skrip . Tapi itu hanya benar jika perintah yang Anda gunakan secara interaktif juga bekerja persis sama ketika dipanggil dalam konteks skrip. Setiap perbedaan signifikan dalam perilaku antara penggunaan interaktif dan penggunaan skrip akan menciptakan semacam disonansi kognitif yang mengganggu pengguna daya.
sumber
rm -rf
sangat efektif, bahkan jika Anda tidak bermaksud menjalankannya di direktori home Anda ...cp
berasal dari awal Unix. Itu ada di sana jauh sebelum standar Posix ditulis. Memang: Posix baru saja meresmikan perilaku yang adacp
dalam hal ini.Kita berbicara tentang Epoch (1970-01-01), ketika pria adalah pria sejati, wanita adalah wanita nyata dan makhluk kecil berbulu ... (saya ngelantur). Pada masa itu, menambahkan kode tambahan membuat program lebih besar. Itu adalah masalah saat itu, karena komputer pertama yang menjalankan Unix adalah PDP-7 (dapat ditingkatkan menjadi 144KB RAM!). Jadi semuanya kecil, efisien, tanpa fitur keselamatan.
Jadi, pada masa itu, Anda harus tahu apa yang Anda lakukan, karena komputer tidak memiliki kekuatan untuk mencegah Anda melakukan apa pun yang Anda sesali kemudian.
(Ada kartun bagus oleh Zevar; cari "zevar cerveaux assiste par ordinateur" untuk menemukan evolusi komputer. Atau coba http://perinet.blogspirit.com/archive/2012/02/12/zevar-et- cointe.html selama itu ada)
Bagi mereka yang benar-benar tertarik (saya melihat beberapa spekulasi dalam komentar): Yang asli
cp
pada Unix pertama sekitar dua halaman kode assembler (C datang kemudian). Bagian yang relevan adalah:(Jadi, sulit
sys creat
)Dan, sementara kita berada di dalamnya: Versi 2 Unix digunakan (sniplet kode)
yang juga sulit
creat
tanpa tes atau perlindungan. Perhatikan bahwa kode-C untuk V2 Unixcp
kurang dari 55 baris!sumber
cp
hanya mengeditopen
tujuan denganO_CREAT | O_TRUNC
dan melakukan aread
/write
loop; tentu, dengan moderncp
ada begitu banyak tombol yang pada dasarnya harus mencoba kestat
tujuan sebelumnya, dan dapat dengan mudah memeriksa keberadaannya terlebih dahulu (dan tidak dengancp -i
/cp -n
), tetapi jika harapan dibuat dari aslinya,cp
alat-alat telanjang , mengubah perilaku itu akan merusak skrip yang ada tanpa perlu. Ini tidak seperti kerang modern denganalias
tidak bisa hanya membuatcp -i
default untuk penggunaan interaktif.creat
kebetulan sama denganopen
+O_CREAT | O_TRUNC
), tetapi kurangnyaO_EXCL
menjelaskan mengapa tidak mudah menangani file yang ada; mencoba melakukannya akan secara inheren bersemangat (pada dasarnya Anda harusopen
/stat
untuk memeriksa keberadaan, kemudian menggunakancreat
, tetapi pada sistem bersama yang besar, itu selalu mungkin pada saat Anda melakukannyacreat
, orang lain membuat file dan sekarang Anda telah meniup tetap pergi). Mungkin juga hanya menimpa tanpa syarat.Karena perintah-perintah ini juga dimaksudkan untuk digunakan dalam skrip, mungkin berjalan tanpa pengawasan manusia, dan juga karena ada banyak kasus di mana Anda memang ingin menimpa target (filosofi dari shell Linux adalah bahwa manusia tahu apa dia melakukan)
Masih ada beberapa perlindungan:
cp
memiliki-n
|--no-clobber
pilihancp
akan mengeluh bahwa yang terakhir bukan direktori.sumber
Komentar ini terdengar seperti pertanyaan tentang prinsip desain umum. Seringkali, pertanyaan tentang ini sangat subyektif, dan kami tidak dapat menulis jawaban yang tepat. Berhati-hatilah karena kami dapat menutup pertanyaan dalam kasus ini.
Terkadang kami memiliki penjelasan untuk pilihan desain asli, karena pengembang telah menulis tentangnya. Tapi saya tidak punya jawaban yang bagus untuk pertanyaan ini.
Kenapa
cp
didesain seperti ini?Masalahnya adalah Unix berusia lebih dari 40 tahun.
Jika Anda membuat sistem baru sekarang, Anda mungkin membuat pilihan desain yang berbeda. Tetapi mengubah Unix akan merusak skrip yang ada, seperti yang disebutkan dalam jawaban lain.
Mengapa itu
cp
dirancang untuk file diam-diam menimpa yang ada?Jawaban singkatnya adalah "Saya tidak tahu" :-).
Pahami itu
cp
hanya satu masalah. Saya pikir tidak ada program komando asli yang dilindungi dari menimpa atau menghapus file. Shell memiliki masalah serupa saat mengarahkan output:Perintah ini juga secara diam-diam menimpa
second.html
.Saya tertarik untuk memikirkan bagaimana semua program ini dapat dirancang ulang. Mungkin membutuhkan beberapa kompleksitas tambahan.
Saya pikir ini adalah bagian dari penjelasan: Unix awal menekankan implementasi sederhana . Untuk penjelasan lebih rinci tentang ini, lihat "lebih buruk lebih baik", terkait di akhir jawaban ini.
Anda bisa mengubahnya
> second.html
sehingga berhenti dengan kesalahan, jikasecond.html
sudah ada. Namun seperti yang kami sebutkan, terkadang pengguna memang ingin mengganti file yang ada. Misalnya, dia mungkin membangun perintah yang rumit, mencoba beberapa kali hingga melakukan apa yang diinginkannya.Pengguna bisa berjalan
rm second.html
dulu jika perlu. Ini mungkin kompromi yang bagus! Ini memiliki beberapa kemungkinan kelemahannya sendiri.rm
. Jadi saya ingin membuatrm
lebih aman juga. Tapi bagaimana caranya? Jika kitarm
menunjukkan setiap nama file dan meminta pengguna untuk mengonfirmasi, dia sekarang harus menulis tiga baris perintah, bukan satu. Juga, jika dia harus melakukan ini terlalu sering, dia akan terbiasa dan mengetik "y" untuk mengonfirmasi tanpa berpikir. Jadi itu bisa sangat menjengkelkan, dan itu masih bisa berbahaya.Pada sistem modern, saya sarankan untuk menginstal
trash
perintah , dan menggunakannya bukanrm
jika memungkinkan. Pengenalan penyimpanan Sampah adalah ide bagus misalnya untuk PC grafis pengguna tunggal .Saya pikir juga penting untuk memahami keterbatasan perangkat keras Unix yang asli - RAM terbatas dan ruang disk, output yang ditampilkan pada printer lambat serta sistem dan perangkat lunak pengembangan.
Perhatikan bahwa Unix asli tidak memiliki penyelesaian tab , untuk dengan cepat mengisi nama file untuk suatu
rm
perintah. (Juga, shell Bourne asli tidak memiliki riwayat perintah, misalnya seperti ketika Anda menggunakan tombol panah Atasbash
).Dengan output printer, Anda akan menggunakan editor berbasis baris
ed
,. Ini lebih sulit dipelajari daripada editor teks visual. Anda harus mencetak beberapa baris saat ini, memutuskan bagaimana Anda ingin mengubahnya, dan mengetik perintah edit.Menggunakannya
> second.html
sedikit seperti menggunakan perintah dalam editor baris. Efeknya tergantung pada kondisi saat ini. (Jikasecond.html
sudah ada, isinya akan dibuang). Jika pengguna tidak yakin tentang keadaan saat ini, ia diharapkan untuk menjalankanls
atau yangls second.html
pertama."Implementasi sederhana" sebagai prinsip desain
Ada interpretasi populer dari desain Unix, yang dimulai:
sumber
cp
"masalah"? Setelah itu secara interaktif meminta izin, atau gagal mungkin merupakan "masalah" sebesar itu.cat first.html second.html > first.html
memberi hasilfirst.html
ditimpa dengan isisecond.html
saja. Konten asli hilang sepanjang waktu.Desain "cp" kembali ke desain asli Unix. Sebenarnya ada filosofi yang koheren di balik desain Unix, yang sedikit kurang setengah bercanda disebut sebagai Worse-is-Better * .
Ide dasarnya adalah bahwa menjaga kode tetap sederhana sebenarnya adalah pertimbangan desain yang lebih penting yang memiliki antarmuka yang sempurna atau "melakukan Hal yang Benar".
( penekanan milikku )
Mengingat bahwa ini adalah tahun 1970, kasus penggunaan "Saya ingin menyalin file ini hanya jika belum ada" akan menjadi kasus penggunaan yang cukup langka bagi seseorang yang melakukan salinan. Jika itu yang Anda inginkan, Anda akan cukup mampu memeriksa sebelum salinan, dan itu bahkan dapat dituliskan.
Mengenai mengapa sebuah OS dengan pendekatan desain kebetulan menjadi salah satu yang menang atas semua OS lain yang sedang dibangun pada saat itu, penulis esai memiliki teori untuk itu juga.
* - atau apa yang penulis, tetapi tidak ada orang lain, yang disebut "The New Jersey approach" .
sumber
creat()
vsopen()
.open()
Tidak dapat membuat file jika itu tidak ada. Hanya dibutuhkan 0/1/2 untuk membaca / menulis / baik. Ini belum mengambilO_CREAT
, dan tidak adaO_EXCL
).Alasan utama adalah bahwa GUI adalah definisi interaktif, sedangkan biner seperti
/bin/cp
hanyalah sebuah program yang dapat dipanggil dari semua jenis tempat, misalnya dari GUI Anda ;-). Saya berani bertaruh bahwa bahkan hari ini sebagian besar panggilan untuk/bin/cp
tidak akan berasal dari terminal nyata dengan pengguna mengetik perintah shell melainkan dari server HTTP atau sistem surat atau NAS. Perlindungan bawaan terhadap kesalahan pengguna masuk akal sepenuhnya dalam lingkungan interaktif; kurang begitu dalam biner sederhana. Sebagai contoh, GUI Anda kemungkinan besar akan memanggil/bin/cp
di latar belakang untuk melakukan operasi aktual dan harus berurusan dengan pertanyaan keamanan tentang standar meskipun itu hanya meminta pengguna!Perhatikan bahwa itu sejak hari pertama yang dekat dengan sepele untuk menulis pembungkus yang aman
/bin/cp
jika diinginkan. Filosofi * nix adalah untuk menyediakan blok bangunan sederhana bagi pengguna: di antaranya/bin/cp
adalah satu.sumber