Bagaimana cara menyalin tautan simbolis?

180

Saya memiliki direktori yang berisi beberapa tautan simbolis:

user@host:include$ find .. -type l -ls
4737414    0 lrwxrwxrwx   1 user group       13 Dec  9 13:47 ../k0607-lsi6/camac -> ../../include
4737415    0 lrwxrwxrwx   1 user group       14 Dec  9 13:49 ../k0607-lsi6/linux -> ../../../linux
4737417    0 lrwxrwxrwx   1 user group       12 Dec  9 13:57 ../k0607-lsi6/dfc -> ../../../dfc
4737419    0 lrwxrwxrwx   1 user group       17 Dec  9 13:57 ../k0607-lsi6/dfcommon -> ../../../dfcommon
4737420    0 lrwxrwxrwx   1 user group       19 Dec  9 13:57 ../k0607-lsi6/dfcommonxx -> ../../../dfcommonxx
4737421    0 lrwxrwxrwx   1 user group       17 Dec  9 13:57 ../k0607-lsi6/dfcompat -> ../../../dfcompat

Saya perlu menyalinnya ke direktori saat ini. Tautan yang dihasilkan harus independen dari prototipe mereka dan mengarah langsung ke objek target mereka.

  • cp -s membuat tautan ke tautan yang bukan perilaku yang pantas.
  • cp -s -L menolak untuk menyalin tautan ke direktori
  • cp -s -L -r menolak untuk menyalin tautan relatif ke direktori yang tidak berfungsi

Apa yang harus saya lakukan?

Basilevs
sumber
10
cp -dmembuat pekerjaan di sisiku.
m-ric
2
cp -Rpada mac
Mirko

Jawaban:

201
cp --preserve=links

Dari halaman manual:

   --preserve[=ATTR_LIST]
          preserve  the   specified   attributes   (default:   mode,owner-
          ship,timestamps),  if  possible  additional attributes: context,
          links, xattr, all

Secara pribadi, saya menggunakan cp -av sebagian besar salinan berat saya. Dengan begitu, saya bisa menjaga semuanya - bahkan secara rekursif - dan melihat hasilnya. Tentu saja, itu hanya preferensi pribadi.

Mengapa opsi Anda yang lain tidak melakukan apa yang Anda harapkan, -sjadikan tautan alih - alih menyalin dan -Likuti tautan di sumber untuk menemukan file yang akan disalin daripada menyalin tautan itu sendiri.

kainosnous
sumber
3
Anda mungkin perlu menambahkan -R, karena jika tidak cp akan melewatkan direktori dan symlink ke direktori.
Olivier 'Ölbaum' Scherler
8
Saya mencoba ini pada redhat dan tidak berhasil
Mansuro
41
di Mac? gunakancp -a
Steve Tauber
11
+1 untuk -aopsi. Heh, aku sudah sering mencari opsi di cphalaman manual, namun aku pasti selalu membaca skim yang satu ini. Saya sampai sekarang telah menggunakan -dpr, tetapi -amencakup semua itu, ditambah pelestarian beberapa atribut lainnya. Jika saya membutuhkan atribut-atribut lain ini, saya mungkin akan mencari --preserveopsi itu lagi dan menggunakan -dr --preserve=all, itulah tepatnya -a! Setidaknya saya tahu sekarang - -asempurna dan inilah yang akan saya gunakan mulai sekarang.
James Haigh
3
Ini tidak berhasil pada Cygwin. --preserve=linksitu tidak cukup. Masih dikatakan cp: omitting directory. Tapi -avberhasil.
Chloe
44

Seperti yang dikatakan halaman manual, gunakan -P.

Ignacio Vazquez-Abrams
sumber
8
pada Mac -Ptidak bekerja pada direktori jadi saya menggunakancp -a
Steve Tauber
4
Terima kasih, saya telah melihat dan mendapat manfaat dari jawaban Anda 3 kali sekarang berbeda kali dalam setahun. Sepertinya tidak bisa mengingatnya!
Siddhartha
Ini berfungsi, tetapi halaman manual saya mengatakan "-P tidak pernah mengikuti tautan simbolis di SOURCE", yang secara intuisi tidak sama dengan "salin symlink sebagai symlink ke tujuan". ("tidak pernah mengikuti" membuatnya terdengar seperti bekerja dalam kombinasi dengan -R)
RM
Ini cp -Ptidak seperti jawaban terpilih teratas oleh @ainosnous bekerja untuk saya. Terima kasih!
tommy.carstensen
Bekerja pada Redhat. Respons yang diterima tidak berfungsi!
Phiber
29

Jika tautan berisi jalur relatif, maka, menyalin tautan tidak akan menyesuaikan jalur relatif. Gunakan readlink, dengan saklar -funtuk mengikuti secara rekursif, untuk mendapatkan jalur absolut tautan. Sebagai contoh:

ln -s $(readlink -f old/dir/oldlink) new/dir/newlink

Jika melestarikan path relatif adalah apa yang Anda inginkan, daripada pilihan -Pdari cp, seperti yang dikatakan oleh Ignacio Vazquez-Abrams, adalah apa yang Anda butuhkan.

mrucci
sumber
1
Mungkin merupakan ide yang buruk untuk melakukan dereferensi secara rekursif jika semua yang Anda coba lakukan adalah mengubah symlink dari relatif menjadi absolut. Rekursi tidak diperlukan di sini, dan terkadang symlink dirantai ada karena suatu alasan. Symlinks sering digunakan untuk menentukan opsi atau opsi konfigurasi. Sebagai contoh, pada sistem saya ada rantai symlink /usr/share/dict/words -> /etc/dictionaries-common/words -> /usr/share/dict/british-englishyang menentukan kamus pilihan. Jika Anda secara rekursif mereferensikan rantai ini, symlink yang dihasilkan akan mengabaikan perubahan apa pun di masa depan untuk preferensi ini.
James Haigh
24

Seperti beberapa yang berkomentar:

cp -a 

bekerja dengan baik.

Dari pria itu:

-a    same as -dR --preserve=all

-R    copy directories recursively
-d    same as --no-dereference --preserve=links
--no-dereference   never follow symbolic links in SOURCE
Juh_
sumber
3
... tetapi hanya jika tidak satu pun dari symlinks adalah jalur relatif.
Michael Scheper
11

Saya menggunakan yang berikut ini untuk menduplikasi direktori yang sangat besar. Semua tautan simbolis dilestarikan, salinannya dilakukan secara rekursif dan saya dapat memiliki beberapa umpan balik visual dari proses:

cp -Prv /sourcer_dir/* /target_dir
oarevalo
sumber
10

Sebagian besar waktu, ketika saya perlu menyalin banyak tautan simbolis, saya sebenarnya mencoba untuk mirror pohon direktori. Jadi saya ingin symlink dan yang lainnya.

Ini berlebihan untuk menyalin hanya beberapa symlink, tetapi jika Anda benar-benar mencoba menyalin seluruh pohon, ini bisa sangat berguna:

Gunakan tar .

user@host:/cwd$ ( cd /path/to/src ; tar cf - . ) | ( cd /path/to/dest ; tar xf - )

tar tidak menyelesaikan symlink secara default, jadi symlink di salinan mirror akan menunjuk ke lokasi yang sama dengan yang di pohon asli.

Trik ini menggunakan subkulit untuk mendapatkan perintah tar ke posisi di root direktori yang akan dicerminkan; Anda dapat mengabaikan salah satunya (bersama dengan perintah cd yang terkait ) jika Anda sudah berada di direktori src atau dest :

# already in src?
user@host:/src$ tar cf - . | ( cd /path/to/dest ; tar xf - )

# already in dest?
user@host:/dest$ ( cd /path/to/src ; tar cf - . ) | tar xf - 

# just need src/foo?
# this result will be a mirror copy at dest/foo 
user@host:/src$ tar cf - foo | ( cd /path/to/dest ; tar xf - )

# mirror to another system?
user@host:/src$ tar cf - . | ssh [email protected] '( cd /path/to/dest ; tar xf - )'

Sekali lagi, ini tidak sesuai untuk setiap kali Anda ingin menyalin tautan simbolis, tetapi ini adalah potongan yang sangat berguna untuk diketahui.

quack quixote
sumber
1
tar jelas lebih portabel daripada cp dalam pengalaman saya
don bright
4

Coba: cp -pr tujuan symlink

[root@station1 temp]# ls -l
total 8
-rw-r--r-- 1 root root  0 Jul 27 18:40 abc
lrwxrwxrwx 1 root root 13 Jul 27 18:41 abc.link1 -> /tmp/temp/abc
[root@station1 temp]# cp -rp /tmp/temp/abc.link1 /tmp/temp/abc.link2
[root@station1 temp]# ls -l
total 12
-rw-r--r-- 1 root root  0 Jul 27 18:40 abc
lrwxrwxrwx 1 root root 13 Jul 27 18:41 abc.link1 -> /tmp/temp/abc
lrwxrwxrwx 1 root root 13 Jul 27 18:42 abc.link2 -> /tmp/temp/abc
[root@station1 temp]# 

OS - Centos 5 (Linux)

eb00
sumber
3

Di Ubuntu saat menyalin tautan dan file di direktori:

cp --no-dereference --preserve=links
Greg
sumber
5
cp -dadalah singkatan untuk ini
hunse
1
Saya pikir keduanya cp -adan cp --preserve=linksmelakukan lebih dari pertanyaan yang diajukan. Seperti yang saya pahami, ini adalah jawaban yang benar untuk siapa pun yang menggunakan cp, meskipun hanya dengan file (tanpa direktori) seperti dalam pertanyaan, tidak --no-dereferenceakan berpengaruh.
palswim
2

Gunakan -Popsi, seperti yang ditulis Ignacio Vazquez-Abrams di atas . Apa yang tidak dia sebutkan adalah -Ptidak berpengaruh tanpa -R. Jadi, Anda setidaknya perlu cp -RP.

(Situs belum mengizinkan saya untuk berkomentar, jadi saya mengirim jawaban yang terpisah.)

1234ru
sumber
Pada kotak solaris lama cp saya tidak mendukung -d. cp -rP bekerja untuk saya; (idk perbedaan antara -R dan -r, -r bekerja untuk saya).
spioter
1

cp -s dan cp -L adalah perintah khusus. Untuk kebutuhan Anda, jangan gunakan.

misalnya Menyalin direktori DIR yang berisi a dan tautan simbolik b yang menunjuk ke a.

  • cp -s DIR / * N / membuat tautan simbolik alih-alih menyalin, N / a -> ../ DIR / a (tautan) dan N / b -> (../ DIR / b) yang merupakan tautan ke tautan
  • cp -L DIR / * N / salinan dengan tautan referensi, N / a, N / b (sama dengan DIR / a)

Yang Anda butuhkan adalah N / a (= DIR / a), dan N / b -> ../ N / a; jadi salin saja tanpa dereferencing, menggunakan opsi cp -P. Saya percaya ini juga default untuk cp.

  • -P no-dereference, pertahankan tautan
  • -d menggabungkan opsi -P dengan -p untuk mempertahankan = mode, kepemilikan, cap waktu
  • -a menggabungkan opsi -d dengan -R untuk menyalin direktori secara rekursif

lihat man cpatau cp --helpuntuk lebih banyak opsi.

Atif Hussain
sumber