Mengapa program unix mv tidak membutuhkan opsi -R (rekursif) untuk direktori tetapi cp memang membutuhkannya?


58

Saya selalu kacau ketika harus menggunakan cpatau mv: "apakah saya perlu -Ropsi saat bekerja dengan dir?" Dalam GNU coreutils cpmemang perlu -Rdan mvtidak.

Saya hanya tidak dapat menemukan alasan mengapa cpperlu -Ropsi untuk menyalin dirs dan mvtidak. Saya pikir bahwa cptanpa instruksi -R(tetapi berperilaku secara rekursif seperti ada -Rdan suka mv) tidak akan menimbulkan masalah kecuali menghentikan kebiasaan seseorang dalam menggunakan alat ini.

Apakah Anda tahu penjelasannya? Mungkin itu punya alasan sejak dulu?


Pertanyaan tambahan: mengapa pengembang coreutils tidak membuat cpdirektori salinan secara rekursif secara default?

Jawaban:


45

Direktori adalah (secara konseptual) sebuah "file" khusus yang berisi daftar nama, dan nomor inode menunjuk ke nama-nama tersebut. Beberapa nama dapat berupa subdirektori. Ada entri khusus ..yang menunjuk ke direktori induk.

Jadi, jelas, mengubah nama file itu mudah: Anda hanya mengubah nama dalam entri direktori, tidak ada yang lain. Ini berlaku apakah file itu sebenarnya file, atau "file" yang digunakan untuk menyimpan konten direktori lain. Memang, renamesyscall yang sama melakukan keduanya.

Menyalin, bagaimanapun, adalah operasi yang jauh lebih sepele. Anda bisa saja menyalin direktori "file", tetapi kemudian Anda akan memiliki dua direktori di mana file-file itu sama (mereka akan berupa hardlink). Jika Anda memiliki sistem yang memungkinkan hardlink ke direktori, itu adalah, tetapi karena tidak ada sistem modern yang memungkinkan, setidaknya untuk non-root, Anda harus melakukan salinan itu untuk setiap subdirektori. Anda sebenarnya dapat meminta cpperilaku ini dengan cp -lR: -luntuk tautan keras, -Runtuk rekursi itu.

Tetapi meninggalkan semua yang terhubung sepertinya bukan yang Anda inginkan. Sebagai gantinya, Anda ingin cpmenyalin setiap file. Itu operasi yang cukup mahal: setiap file harus dibaca ke dalam memori, dan ditulis kembali ke disk di lokasi kedua. Sebenarnya dibutuhkan beberapa syscalls, untuk membuka, membaca, menulis, dan menutup file, dan itu harus diulang untuk setiap file.

Sistem file tradisional juga bekerja dengan cara ini pada disk. Tidak ada cara untuk menyalin banyak file, selain untuk pergi melalui masing-masing secara individual dan menyalinnya, dan itu adalah jenis-jenis sistem file yang digunakan ketika utilitas baris perintah dasar dirancang.


apakah mvdari satu sistem file ke sistem file yang lain sama "hanya mengubah nama dalam entri direktori"?
rslnx

5
Tidak, cross-filesystem sama dengan copy + delete (memang, renamesyscall akan gagal untuk cross-filesystem). Tidak yakin apakah, secara historis, mvbahkan mendukung gerakan lintas-fs.
derobert

9
Saya dapat memberitahu Anda, dari pengalaman langsung bukan spekulasi, bahwa klasik mvtidak mendukung gerakan lintas perangkat. Dulu hanya mencoba rename()dan mencetak pesan kesalahan jika gagal. Saya masih ingat perasaan kaget saya saat pertama kali saya tidak sengaja menggunakan fitur baru. Mengapa mv ini begitu lama? Oh, itu melakukan salinan rekursif yang saya tidak bermaksud!
Alan Curry

5
@RuslanKhusnullin Opsi baris perintah ke perintah umum sangat sulit diubah, karena penggunaannya dalam skrip shell. Seseorang mungkin tergantung pada perilaku menolak-untuk-menyalin-dir saat ini dari cp. Hal-hal lintas-fs mungkin dinilai cenderung menyebabkan kerusakan, meskipun seperti yang Anda lihat, masih mengejutkan Alan.
derobert

1
@derobert, tidak (cross-filesystem mvhanya berfungsi untuk file individual di BSD 4.2 di VAX).
vonbrand

21

Biarkan saya mulai dengan mengajukan pertanyaan lain:

Apa perbedaan antara cpdan cp -R?

Nah, tanpa -Rtanda, itu hanya mungkin untuk menyalin file, karena itu agak tidak biasa bahwa seseorang ingin secara non-rekursif menyalin direktori: Salinan non-rekursif hanya akan menghasilkan nama kedua untuk direktori, menunjuk langsung ke direktori yang sama struktur. Karena itu jarang yang diinginkan orang, dan sebenarnya ada program terpisah yang melakukan ini ( ln), salinan direktori non-rekursif tidak diperbolehkan.

Lalu apa yang bisa menjadi perbedaan antara mvdan mv -R?

mv a bhanya mengganti nama entri tunggal di direktori, jadi jika direktori mvdiedit, isinya secara otomatis juga dipindahkan. Dalam pengertian itu, mvsudah menyediakan properti rekursif, yaitu "penggantian nama" dari semua entri dalam direktori yang diubah namanya, misalnya dari a/1ke b/1. Sebuah mvyang tidak melakukan hal itu, yaitu yang mengganti nama direktori auntuk b, namun tetap a/1seperti a/1, tidak apa yang orang mengerti ketika mereka merujuk bergerak sesuatu: Bila Anda memindahkan lemari, isi lemari dipindahkan juga. Operasi lain itu, memindahkan direktori tanpa isinya, juga sudah tersedia, namanya mkdir.


2
Itu benar, saya hanya memikirkan cpdan mvsebagai operasi mereka diberi nama: 'buat salinan' dan 'pindah'. Jadi, jika saya ingin membuat salinan secangkir kopi, saya akan berharap untuk minum secangkir kopi dengan isian yang sama (minuman kopi). Masalahnya adalah bahwa alat tidak dimaksudkan untuk 'orang biasa' tetapi untuk kutu buku yang mengetahui struktur sistem disk dan file, bukan entitas virtual seperti file dan direktori file.
rslnx

1
Respon yang terstruktur dan beralasan.
Spedge

1
@RuslanKhusnullin Analogi kopi Anda bekerja untuk cpdan mvjuga - itu tidak memerlukan tingkat "kebodohan" untuk memahami, hanya akal sehat dasar. Kopi sejati secangkir kopi bukanlah cangkir kosong - Anda harus menyalin tidak hanya cangkir secara rekursif, tetapi semua isinya (kopi) juga. Namun, ketika Anda memindahkan secangkir kopi Anda tidak harus memindahkan isinya secara terpisah - isinya bergerak dengan wadah secara alami.
jw013

1
@ jw013 Anda membuat saya terkesan dengan "ketika Anda memindahkan secangkir kopi Anda tidak perlu memindahkan isinya secara terpisah", itu sangat masuk akal, terima kasih. Tapi itu lapisan abstraksi lain. Saya pikir maksud Anda "memperlakukan file sebagai inode" sementara saya memikirkan file seperti urutan byte tanpa meta-informasi.
rslnx

6

Biasanya ketika saya kacau dengan logika Unix saya melihat Plan9 untuk melihat bagaimana penemu Unix melaksanakan tugas yang sama bertahun-tahun kemudian tanpa berhenti pada kompatibilitas ke belakang.

Jadi Plan9 menawarkan cpdan mvalat untuk beroperasi dengan file saja.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Untuk menyalin dir ada dircpyang benar-benar @{cd fromdir && tar c .} | @{cd todir && tar xT}(rc shell syntax)

Untuk memindahkan dir, saya pikir hanya ada dircp d1 d2 && rm -r d1

Saya pikir keputusan ini untuk membatasi cpdan hanya mvuntuk operasi file (bukan dirs) membawa lebih jelas untuk operasi disk dan menggunakan taruntuk menyalin pohon file sangat nyaman untuk memahami dan scripting.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.