Apa nilai tambah dari opsi -T di GNU cp dan mv?

26

Mengapa beberapa perintah GNU Coreutils memiliki -T/--no-target-directoryopsi? Sepertinya semua yang dilakukannya dapat dicapai dengan menggunakan semantik .(titik diri) dalam hierarki direktori Unix tradisional.

Mengingat:

cp -rT /this/source dir

The -Tpilihan mencegah salinan dari menciptakan dir/sourcesubdirektori. Sebaliknya /this/sourcediidentifikasi dengan dirdan isinya dipetakan di antara pohon sesuai. Jadi misalnya /this/source/foo.cpergi ke dir/foo.cdan seterusnya, bukan ke dir/source/foo.c.

Tetapi ini dapat dengan mudah dilakukan tanpa -Topsi menggunakan:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Secara semantik, komponen titik jejak disalin sebagai anak dir, tetapi tentu saja "anak" itu sudah ada (jadi tidak harus dibuat) dan sebenarnya diritu sendiri, sehingga efeknya adalah yang /this/pathdiidentifikasi dir.

Ini berfungsi dengan baik jika direktori saat ini adalah target:

cp -r /this/tree/node/. . # node's children go to current dir

Apakah ada sesuatu yang dapat Anda lakukan hanya dengan -Titu dapat merasionalisasi keberadaannya? (Selain dukungan untuk sistem operasi yang tidak mengimplementasikan direktori dot, alasannya tidak disebutkan dalam dokumentasi.)

Apakah dot trick di atas tidak menyelesaikan kondisi balapan yang sama dengan yang disebutkan dalam dokumentasi Info GNU -T?

Kaz
sumber

Jawaban:

29

.Trik Anda hanya dapat digunakan saat Anda menyalin direktori, bukan file. The -Tpilihan bekerja dengan baik direktori dan file. Jika kamu melakukan:

cp srcfile destfile

dan sudah ada direktori destfileyang akan disalin destfile/srcfile, yang mungkin tidak dimaksudkan. Jadi, Anda gunakan

cp -T srcfile destfile

dan Anda mendapatkan kesalahan dengan benar:

cp: cannot overwrite directory `destfile' with non-directory

Jika Anda mencoba menggunakan .metode ini, salinannya tidak akan pernah berfungsi:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
sumber
The .trick melakukan pekerjaan saat menyalin file, hanya saja tidak ketika mengubah nama basename nya pada saat yang sama! cp /path/to/file /target/dir/. Jika /target/dir/fileada dan merupakan direktori, Anda mendapatkan diagnostik yang sama! Tetapi Anda telah menunjukkan apa -Tyang tidak dapat dilakukan tanpanya dalam satu langkah, tanpa syarat balapan: salin file dan ubah namanya tanpa disuntikkan ke subdirektori.
Kaz
3
Itu tidak sama - .trik yang Anda bicarakan adalah menambahkan /.ke sumbernya .
Barmar
21

Masalahnya dengan cp/ mv/ lnsebagaimana aslinya dirancang adalah bahwa mereka adalah dua perintah dalam satu ( salin ke dan salin ke ).

cp A B

adalah menyalin A ke B atau menyalin A ke B ( menyalin A ke B / A ) tergantung pada apakah Bada dan merupakan direktori atau tidak (dan lebih banyak variasi jika B adalah symlink ke direktori).

Itu buruk karena tidak jelas. Jadi implementasi GNU telah menambahkan opsi untuk mengatasinya.

cp -T A B

salinan A ke B tanpa memperhatikan. Jika Bada dan merupakan direktori, itu akan gagal (kecuali Anda lulus -r). Bagaimanapun, Anda tidak akan berakhir dengan Afile di dalamnya Bketika Anda bermaksud Auntuk disalin ke B.

Dan:

cp -t B A

adalah salinan .

Stéphane Chazelas
sumber
Filosofi unix yang asli adalah mengasumsikan Anda tahu apa yang Anda lakukan, dan dengan senang hati akan membiarkan Anda menembak diri sendiri.
Lenne
4
@Lenne, tapi ini tidak memberi Anda cara untuk menghindari menembak diri sendiri di kaki. Jika seseorang membuat direktori B atau symlink ke beberapa direktori sebelum Anda menjalankan cp A Bperintah tidak akan melakukan apa yang Anda inginkan. Dan [ -e B ] || [ -L B ] || cp A Bmasih memiliki kondisi ras yang cp -Tn A Btidak memiliki.
Stéphane Chazelas
6

Itu -Tdapat memberikan kegagalan jika ada direktori yang salah untuk apa yang seharusnya menjadi file tujuan:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

Yaitu, alih-alih sukses-di-tak terduga-menyalin-ke-subdir, peringatan dan status keluar yang tidak baik terjadi, yang kemudian dapat menyebabkan skrip dibatalkan, dan manusia memeriksa mengapa ada direktori di mana seharusnya tidak ada menjadi satu.

thrig
sumber
0

Menggunakan bendera juga jauh lebih jelas, dan memiliki risiko lebih kecil dari efek yang tidak diinginkan, ketika perintah digunakan dalam skrip alih-alih dimasukkan secara manual. Menambal titik-titik ke jalan dalam sebuah skrip bisa berakhir dengan segala macam kerusakan tak terduga.

pemeras
sumber