“Değişirse kopyala” işlemini nasıl yapabilirim?


34

A dizinden B dizine bir dizi dosya kopyalamak istiyorum, A dizindeki bir dosyanın B dizindeki bir dosya ile aynı olması durumunda, o dosyanın kopyalanmamasını ihmal etmeliyim (ve bu nedenle değişiklik zamanı olmamalıdır) güncellenmiş). Bunu yapmak için kendi komut dosyasını yazmadan, mevcut araçlarla bunu yapmanın bir yolu var mı?

Kullanım durumumdan biraz bahsetmek için: .cGeçici bir dizinde (hepsini koşulsuz olarak üretmek zorunda olan bir yöntemle) bir grup dosyayı otomatik olarak oluşturuyorum ve bunları yeniden oluştururken yalnızca kopyalamak istiyorum Asıl kaynak dizine giren, değişmeyenleri dokunmadan bırakanlar (eski oluşturma zamanlarıyla) böylece makeyeniden derlemeye gerek duymayacaklarını bileceklerdir. (Oluşturulan dosyaların tümü .cdosya değildir, bu yüzden metin karşılaştırmaları yerine ikili karşılaştırmalar yapmam gerekir.)

(Not olarak: Bu , denediğim https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 adresinde sorduğum sorudan çıktı. komut dosyasını hızlandırmak için bu işlemi yapmak için kullanıyordum, ancak bana şunu yazmalıyım ki, bunu yapmanın daha iyi bir yolu olup olmadığına bakmalıyım - özellikle bunu kabuğun içinde yapmanın basit bir yolu olduğundan komut dosyası cmp, her dosya çiftine benzer bir şey çağırır ve tüm bu işlemlerin başlatılması çok uzun sürer.


1
diff -qr dirA dirBHangi dosyaların benzersiz dirAve dirBsırayla olduğunu görmek için kullanabilirsiniz .

1
@ brooks-moses bu gerçekten ccache için uygun bir iş !
aculich

3
@hesse eğer eşsiz dosyaları göstermek istiyorsanız diff kullanabilirsiniz, fakat sadece neyin değiştiğini görmek istiyorsanız kullanın rsync -avncya da uzun yoldan kullanın rsync --archive --verbose --dry-run --checksum.
aculich

Yanıtlar:


29

rsync muhtemelen bunun için en iyi araçtır. Bu komutta birçok seçenek var, bu yüzden man sayfasını okuyun . - checksum seçeneğini veya --ignore-times'ı istediğinizi düşünüyorum


Bunu çoktan denediğimi not etmeliydim, başarı olmadan. Bu seçeneklerin ikisi de yalnızca rsync'in bir kopya yapıp yapmadığını etkiler - ancak, bir kopya yapmasa bile, hedef dosyanın değişiklik zamanını kaynakla aynı ( -tseçenek belirtilirse) veya senkronizasyon zamanıyla günceller ( -tbelirtilmemişse).
Brooks Moses

4
@ Musa Yüceliyor: Öyle değil. En azından benim versiyonum rsyncdeğil. Bunu yaparsam: mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* desto zaman stat dest/asaatini gösterir ve ctime olanlardan 5 saniye daha eskidir src/a.
angus

@ angus: Huh. Tamam, haklısın. Anahtar gibi görünüyor --checksumseçeneği ve her ne linux.die.net/man/1/rsync kesinlikle içeren hiçbir şey , herhangi bir değişiklik tarihi güncellendiğinde olmadığına etkileyen sahip olduğunu ifade eder, yine de bırakılmak hedef değiştirme tarihini neden olur bakir. (Öte yandan, --ignore-timesseçeneğin bu etkisi yoktur; bununla birlikte değişiklik tarihi hala güncellenmektedir.) Bunun tamamen belgelenmemiş olduğu göz önüne alındığında, buna güvenebilir miyim?
Brooks Moses

2
@BrooksMoses: Ona güvenebileceğinizi düşünüyorum: rsynciş akışı: 1) dosyanın güncellenmesi gerekip gerekmediğini kontrol edin; 2) öyleyse, dosyayı güncelleyin. --checksumSeçenek yüzden güncellenmesi gerektiğini söylüyorlar rsync) 2. adımda geçin olmamalıdır.
enzotib

2
@BrooksMoses: --ignore-timesolmadan --checksumher dosyayı kopyalar ve böylece dosyalar aynı olsa bile zaman damgasını günceller.
enzotib

13

Beğenmek için -udüğmeyi kullanabilirsiniz cp:

$ cp -u [source] [destination]

Man sayfasından:

   -u, --update
       copy only when the SOURCE file is newer than the destination file or 
       when the destination file is missing

4
Merhaba ve siteye hoşgeldiniz. Burada cevapların biraz daha önemli olmasını bekliyoruz. Örneğin, -ubayrağın ne yaptığı, nasıl çalıştığı ve bunun OP'ye nasıl yardımcı olacağı hakkında bir açıklama ekleyebilirdiniz. Bununla birlikte, bu özel durumda, eğer daha yeni olsaydı aynı dosyaları kopyalayacağı için OP'ye yardımcı olmaz ve bu yüzden OP'nin kaçınmak istediği tam olarak zaman damgalarını değiştirirdi.
terdon

1
Daha önce silinmiş olan benzer bir A yorumundan: "Eğer kaynak zaman damgası daha yeniyse (ve dolayısıyla OP isteğine göre hedefin zaman damgasını güncelle), bu aynı dosyaları kopyalayacağından işe yaramayacaktır."
slm

Soruyu hiç cevaplamıyor ama yine de faydalı buldum.
user31389,

7

Kullanmak rsync --checksum"değiştirilirse kopyalamak" için iyi bir genel yol olsa da, kendi durumunuzda daha iyi bir çözüm var!

Gereksiz yere dosya derlemekten kaçınmak istiyorsanız, tam olarak bu amaç için oluşturulmuş ccache'yi kullanmalısınız ! Aslında, sadece otomatik olarak oluşturulan dosyalarınızı gereksiz yere yeniden derlemekten kaçınmakla kalmaz, aynı zamanda yaptığınız her şeyi hızlandırır make cleanve sıfırdan derler.

Sonra eminim ki "Güvenli mi?" Evet, web sitesinin işaret ettiği gibi:

Güvenli mi?

Evet. Bir derleyici önbelleğinin en önemli yönü, her zaman gerçek derleyicinin üreteceği çıktı ile aynı çıktıyı üretmektir. Bu, gerçek derleyiciyi kullanırsanız, tam olarak aynı nesne dosyalarının ve tam olarak aynı derleyici uyarılarının verilmesini içerir. Ccache kullandığınızı söylemenin tek yolu hızdır.

Ve sadece makefile satırınıza bir ön ek olarak ekleyerek kullanımı kolaydırCC= (veya sembolik bağlantılar kullanabilirsiniz, ancak makefile yolu muhtemelen daha iyidir).


1
Başlangıçta yanlış anladım ve ürettiğin bir bölümünü yapmak için ccache kullandığımı düşündüğünüzü düşündüm, ama şimdi anlıyorum - öneriniz, tüm dosyaları kopyaladığım ve daha sonra derleme işleminde ccache kullandığımdan, değişmemişti. Bu iyi bir fikir, ama benim durumumda iyi olmaz - yüzlerce dosyam var, genellikle sadece bir ya da iki tanesini değiştirebiliyorum ve Cygwin altında çalışıyorum. dosya birkaç dakika sürer. Bununla birlikte, çoğu insan için iyi bir cevap olduğu için, olumlu eleştiriler yapıldı!
Brooks Moses

Hayır, tüm dosyaları kopyalamanızı önermiyordum, bunun yerine sadece .c dosyalarınızı yerinde otomatik olarak oluşturabilirsiniz (kopya adımını kaldırın ve doğrudan bunlara yazın). Ve sonra sadece ccache kullanın. Yüzlerce önbellek işlemi başlatarak ne demek istediğinizi bilmiyorum ... bu sadece gcc etrafında hafif bir sargıdır ve oldukça hızlıdır ve projenizin diğer bölümlerinin yeniden oluşturulmasını hızlandıracaktır. Kullanmayı denedin mi? Copy-method vs ccache kullanımınız arasındaki zamanlama karşılaştırmasını görmek isterim. Aslında, ikisinin de avantajlarını elde etmek için iki yöntemi birleştirebilirsiniz.
aculich

1
Tamam, tamam, şimdi kopyalamayı anlıyorum. Açıklamak gerekirse, demek istediğim şudur: Dosyaları yerinde ccache file.c -o file.otutarsam, birkaç kez yüzlerce file.cdosya olduğundan birkaç kez defa aramam gerekir . Ben o yapıyordu zaman cmpyerine ccache, birkaç dakika sürdü - ve cmphem hafif gibidir ccache. Sorun şu ki, Cygwin'de bir sürece başlamak tamamen önemsiz bir süreç için bile ihmal edilemez bir zaman alıyor.
Brooks Moses

1
Bir veri noktası olarak, for f in src/*; do /bin/true.exe; done30 saniye sürer, yani evet. Her neyse, Windows tabanlı editörümü tercih ediyorum ve bu tür bir zamanlama meselesinin bir yana, Cygwin, yapı sunucularına yükleme yapmazsam işleri yerel olarak test etmek için hafif bir yer olarak iş akışımla oldukça iyi çalışıyor. Kabuğumu ve editörümü aynı işletim sisteminde kullanmakta fayda var. :)
Brooks Moses

1
Eğer Windows tabanlı editörünüzü kullanmak istiyorsanız, Konuk Eklemeleri yüklerseniz bunu Paylaşılan Klasörler ile kolayca yapabilirsiniz ... ama hey, Cygwin size uygunsa, o zaman kim farklı diyebilirim? Bunun gibi garip çemberlerin içinden atlamak utanç verici görünüyor ... ve genel olarak derleme de VM'de daha hızlı olur.
aculich

3

Bu ihtiyacınız olanı yapmalı

diff -qr ./x ./y | awk '{print $2}' | xargs -n1 -J% cp % ./y/

Nerede:

  • x güncellenmiş / yeni klasörünüzdür
  • y, kopyalamak istediğiniz hedef
  • awk, her bir satırın ikinci argümanını diff komutundan alır (belki boşluk içeren dosya adları için fazladan bir şeyler yapmanız gerekebilir - şimdi deneyemezsiniz)
  • xargs -J% uygun yere cp dosya ismini ekler

1
-1 çünkü bu aşırı derecede karmaşık, taşınabilir değil ( -Jbsd'ye özgüdür; GNU xargs ile -I) ve aynı dosya grubu zaten her iki yerde de mevcut değilse, (eğer touch x/boogrep verirseniz) düzgün çalışmıyor Only in ./x: booboru hattında hatalara neden olan). Gibi iş için inşa edilmiş bir araç kullanın rsync --checksum.
aculich

Ya da daha iyisi, bu özel durum için ccache kullanın .
aculich

+1, benzer görevlerde kullanmak için kırabileceğim, çok iyi bilinen bir komutlar dizisi olduğundan (buraya bir
zorunluluk

3

Unison'u lehine kullanmaktan hoşlanıyorum rsyncçünkü ssh anahtarlarını ve vpn'yi ayrı ayrı ayarladıktan sonra birden fazla master'ı destekliyor .

Bu yüzden sadece bir ana bilgisayarın crontab'ında her 15 dakikada bir senkronize etmelerine izin veriyorum:

* / 15 * * * * [-z "$ (birlikte unid)"] && (zaman aşımı 25m dev -logfile /tmp/sync.master.dev.log) &> /tmp/sync.master.dev.log

O zaman her iki tarafta da gelişebilirim ve değişiklikler yayılır. Aslında, önemli projeler için aynı ağacı yansıtan 4 adede kadar sunucum var (3'ü cron'dan eşleştirerek çalıştıranlara işaret ediyor). Aslında, Linux ve Cygwin karışık bir şekilde ev sahipliği yapıyor - ancak cy32win ortamının dışındaki win32'deki yumuşak bağlantılardan bir anlam beklemeyin.

Bu rotaya giderseniz, başlangıç ​​aynasını boş tarafa -batch, yani

unison -ui text  -times /home/master ssh://192.168.1.12//home/master -path dev

Tabii ki, yedekleme dosyalarını, arşivleri vb. Yoksaymak için bir yapılandırma vardır.

 ~/.unison/default.prf :
# Unison preferences file
ignore = Name {,.}*{.sh~}
ignore = Name {,.}*{.rb~}
ignore = Name {,.}*{.bak}
ignore = Name {,.}*{.tmp}
ignore = Name {,.}*{.txt~}
ignore = Name {,.}*{.pl~}
ignore = Name {.unison.}*
ignore = Name {,.}*{.zip}

    # Use this command for displaying diffs
    diff = diff -y -W 79 --suppress-common-lines

    ignore = Name *~
    ignore = Name .*~
    ignore = Path */pilot/backup/Archive_*
    ignore = Name *.o

Buna baktım, ancak unison"son dosya değiştirilme tarihlerini güncelleme" anlamına gelen bir seçenek bulamadım . Bir tane var mı? Aksi takdirde, bu tamamen farklı bir soruna harika bir cevap.
Brooks Moses

1
-timesBunu benim için yapar. Unison'un da kuru çalışma modu var sanırım.
Marcos

Eh, ayar times=false(veya bırakarak -times) bunu yapar. Daha önce belgelerde bunu nasıl özlediğimi bilmiyorum. Teşekkürler!
Brooks Moses

Yardım etmekten memnun oldum. Modtimes, izinler ve yumuşak bağlantılar gibi şeyleri korumak söz konusu olduğunda ben bir yapıştırıcıyım. Genellikle gözden kaçan
Marcos

1

rsync --checksumDoğru cevap olsa da, bu seçeneğin uyuşmaz --timesolduğunu ve --archiveiçerdiğini de unutmayın, bu --timesnedenle rsync -a --checksumisterseniz gerçekten yapmanız gerekir rsync -a --no-times --checksum.


'Uyumsuz' derken ne demek istiyorsun?
ov

"Doğru cevap" derken ne demek istiyorsun?
thoni56
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.