linux birleştirme klasörleri: rsync?


13

Bir klasörün iki kopyası var

src/
dest/

Aşağıdakileri yaparak onları birleştirmek istiyorum:

Bir dosya sadece içindeyse src, dosyanın taşınmasını istiyorumdest

Bir dosya sadece içinde ise dest, IE yalnız bırakılmasını istiyorum.

Bir dosya her ikisinde de varsa ve aynı içeriğe sahipse (IE aynı boyutta ve tarihte),src

Bir dosya her ikisinde de varsa ve aynı içeriğe sahip değilse , srcbunları elle birleştirebilmem için geride bırakın .

Çok az sayıda dosya (toplam dosyaların% 0 ila% 5'i arasında) bu son kategoride olmalıdır, ancak her ikisinde de aynı olanı, ancak farklı olanı nasıl ayıracağımı bilmiyorum.

Bunu nasıl yapacağımı anlamaya çalıştım rsyncama şimdiye kadar boşuna.

Yanıtlar:


17

Yalnızca sınırlı işlevsellik testi yaptım, bu yüzden lütfen bu komutla (--dry-run) dikkatli olun:

rsync -avPr --ignore-existing --remove-source-files src/ dest

Lütfen izlemeye dikkat edin / src'nin kendisini kopyalamak yerine src'ye geri döneceğinden, bu, mevcut yollarınızı korumalıdır.

--İgnore-varolan bayrağı --remove-source-files bayrağıyla birlikte kullandığınızda, yalnızca src'den src'den dest'e eşitlenen dosyaları, yani daha önce yalnızca dest'de bulunmayan dosyaları silmiş olursunuz.

Senkronize edilmemiş dosyaları silmek için, yani dest / as içinde src / dizininde bulunan dosyaları silmek için şunları kullanabilirsiniz:

for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done

veya

find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;

dosya adları boşluk / yeni satırlar içerebilirse… Gilles'in özel karakterlerle ilgili yorumu ile ilgili olarak, bu kesinlikle dikkat edilmesi gereken bir şeydir ve birçok çözüm vardır, en basit olanı, tüm silmeden önce komut verecek bir -i'den rm'ye geçmek olacaktır. Ancak, tam nitelikli yolun bulmak için src / veya üst yolunun sağlanması şartıyla, tüm dosya adlarının hem diff hem de rm komutları tarafından tırnak işareti olmadan düzgün bir şekilde işlenmesine neden olmalıdır.


düzeltme: hedefte aynı bir kopya varsa bu komut dosyaları src'den kaldırmaz
Tok

Evet :(.
Anlamakta

2
İyi haber şu ki, çok fazla güçlük çekmeden bağımsız olarak çözebilirsiniz: for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done(isterseniz, atlayabilirsiniz, || echo $filebütünlük için dahil edilmiştir)
Tok

Nifty: Buna ihtiyacım vardı. Cevabınızı düzenleyin, kabul ediyorum!
David Oneill

@Tok: Komutunuz özel karakterler içeren dosya adlarını (boşluk \?*[, ilk -) boğar . Buna gerek değişken değiştirmelerin çift tırnak kullanmak , pas --, dosya adları önce kamu için kullanmak find … -exec …çıktısını ayrıştırma yerine find. Karışımda bir rmkomutla, bu felaket için bir reçetedir.
Gilles 'SO- kötü olmayı kes'

6

unison , aradığınız araçtır. Bir GUI'yi tercih ediyorsanız unison-gtk'yi deneyin. Ama benzer dosyaları sileceğini sanmıyorum: unison her iki dizinin de aynı olmasını sağlamaya çalışın. Bununla birlikte, 1) hangi dosyaların kopyalanacağını kolayca belirleyecektir; 2) hangilerinin manuel birleştirmeye ihtiyacı vardır.


OP'nin tam olarak istediği şeyi yapmaz, ancak OP'nin nihai hedefine ulaştığı anlaşılır. +1
Ryan C. Thompson

+1 Ne yazık ki, üzerinde çalıştığım sunucu unison yüklü değil, ne de yüklemek için izinlere sahip. Ama bu başka birine iyi bir cevap olabilir.
David Oneill

1
Unison yürütülebilir dosyasını seas.upenn.edu/~bcpierce/unison//download/… adresinden indirebilirsiniz . Ana dizininizde bir yere kurun, sadece bir dosya.
JooMing

2

Aşağıdaki komut dosyası işleri makul şekilde yapmalıdır. Dosyaları kaynaktan hedefe taşır, hiçbir zaman bir dosyanın üzerine yazmaz ve gerektiği şekilde dizin oluşturmaz. Hedefte karşılık gelen farklı bir dosyaya sahip kaynak dosyalar, normal dosya veya dizin olmayan dosyalar (örn. Sembolik bağlantılar) tek başına bırakılır. Kaynakta kalan dosyalar, çakışması olan dosyalardır. Dikkat edin, hiç test etmedim.

cd src
find . -exec sh -c '
    set -- "/path/to/dest/$0"
    if [ -d "$0" ]; then #  the source is a directory 
      if ! [ -e "$1" ]; then
        mv -- "$0" "$1"  # move whole directory in one go
      fi
    elif ! [ -e "$0" ]; then  # the source doesn't exist after all
      :  # might happen if a whole directory was moved
    elif ! [ -e "$1" ]; then  # the destination doesn't exist
      mv -- "$0" "$1"
    elif [ -f "$1" ] && cmp -s -- "$0" "$1"; then  # identical files
      rm -- "$0"
    fi
  ' {} \;

Başka bir yaklaşım , örneğin, funionfs veya unionfs -fuse gibi, bir dizini diğerinin üzerine monte etmek olacaktır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.