Bagaimana cara menyalin struktur direktori tanpa menghapus symlink?

27

Saya perlu "menginstal" banyak file ke direktori lain agar struktur direktori file sumber tetap utuh. Sebagai contoh, jika saya ./foo/bar/baz.txtakan /var/www/localhost/webroot/saya ingin hasilnya menjadi /var/www/localhost/webroot/foo/bar/baz.txt. rsyncmemiliki kemampuan ini --relative, tetapi ketika saya melakukan ini saya menemukan itu tidak ramah untuk symlink:

$ ls -ald /var/www/localhost/webroot/ | grep ^l
lrwxrwxrwx  1 www-data www-data     15 2014-01-03 13:45 media -> ../static/media
lrwxrwxrwx  1 root     root         13 2014-02-24 13:47 var -> ../static/var
$ rsync -qrR . /var/www/localhost/webroot/
$ ls -ald /var/www/localhost/webroot/ | grep var
drwxr-xr-x 3 root root 4096 2014-02-24 13:52 /var/www/localhost/webroot/var

Jadi Anda melihat symlink bukan lagi symlink - file disalin ke tempat yang salah!

rsyncjuga memiliki --no-implied-dirsopsi, yang dangkal tampaknya melakukan apa yang saya inginkan, tetapi hanya berfungsi seperti yang saya inginkan ketika tidak melakukan rsync rekursif, jadi saya harus:

find . -type f -print0 | xargs -0I{} rsync -R --no-implied-dirs {} /var/www/localhost/webroot/

Apakah ada cara lain yang lebih langsung untuk mencapai mirroring file ini tanpa menghapus direktori symlink menengah (dengan atau tanpa rsync)?

kojiro
sumber

Jawaban:

42

Gunakan rsyncopsi -K( --keep-dirlinks). Dari halaman manual:

 -K, --keep-dirlinks
      This  option  causes  the  receiving side  to  treat  a
      symlink  to  a  directory  as though  it  were  a  real
      directory, but only if it matches a real directory from
      the  sender.   Without   this  option,  the  receiver’s
      symlink  would  be deleted  and  replaced  with a  real
      directory.

      For example, suppose you  transfer a directory foo that
      contains a file file, but foo is a symlink to directory
      bar  on  the  receiver.  Without  --keep-dirlinks,  the
      receiver  deletes  symlink  foo,   recreates  it  as  a
      directory,  and   receives  the   file  into   the  new
      directory.   With --keep-dirlinks,  the receiver  keeps
      the symlink and file ends up in bar.

      One note  of caution:  if you  use --keep-dirlinks, you
      must  trust all  the symlinks  in the  copy!  If  it is
      possible  for an  untrusted  user to  create their  own
      symlink to  any directory,  the user  could then  (on a
      subsequent  copy)  replace  the  symlink  with  a  real
      directory and affect the  content of whatever directory
      the  symlink references.   For backup  copies, you  are
      better off using something like a bind mount instead of
      a symlink to modify your receiving hierarchy.

      See also  --copy-dirlinks for  an analogous  option for
      the sending side.
angus
sumber
16

Saya ingin mempertahankan symlink saya sebagai symlink. Untuk itu Anda bisa menggunakan opsi -l.

    -l, --links                 copy symlinks as symlinks

Karena saya menyalin kerangka kerja pada OS X, saya merasa ini sangat membantu.

Ben Flynn
sumber
3

Silakan gunakan -a, karena ini menyiratkan -lseperti yang seharusnya di atas. Tetapi juga berisi opsi penting lainnya jika Anda ingin salinan lengkap dari sumber.

Juga: Saat saya memahami halaman manual, -Kdimaksudkan untuk symlink di sisi penerima. Saya kira ini bukan jawaban yang tepat.

Christian Gut
sumber
2

Sebagai rsyncjawaban, tarutilitas dapat melakukan tugas ini. Gunakan dua contoh tardi kedua sisi pipa, yang pertama mengkonsumsi struktur direktori dan yang kedua untuk mengekstraknya di tempat lain. Kepemilikan file salinan kemungkinan akan berubah, sementara mode izin kemungkinan akan tetap tidak berubah.

Banyak contoh ada dan saya menemukan saran dalam jawaban ini relatif cepat: /unix//a/59108/34251 .

Sunting
Contoh kedua (lebih ringkas?): Https://unix.stackexchange.com/a/19824/34251 .

crw
sumber