मैं एक "कॉपी को कैसे बदल सकता हूँ" ऑपरेशन कर सकते हैं?


34

मैं निर्देशिका ए से निर्देशिका बी तक की फाइलों के एक सेट को कैविएट के साथ कॉपी करना चाहूंगा कि यदि निर्देशिका ए में एक फाइल निर्देशिका बी में एक फ़ाइल के समान है, तो उस फाइल को कॉपी नहीं किया जाना चाहिए (और इस प्रकार इसका संशोधन समय नहीं होना चाहिए। अद्यतन)। क्या ऐसा करने का कोई तरीका है, मौजूदा टूल्स के साथ, बिना अपनी स्क्रिप्ट लिखने के लिए?

मेरे उपयोग-मामले पर थोड़ा विस्तार करने के लिए: मैं .cएक अस्थायी निर्देशिका में फ़ाइलों का एक गुच्छा ऑटोजेनरेट कर रहा हूं (एक विधि द्वारा जो बिना शर्त उन सभी को उत्पन्न करना है), और जब मैं उन्हें फिर से उत्पन्न करता हूं, तो मैं केवल कॉपी करना चाहूंगा जो वास्तविक स्रोत निर्देशिका में बदल गए हैं, अपरिवर्तित लोगों को अछूता छोड़ रहे हैं (उनके पुराने निर्माण के समय के साथ) ताकि makeउन्हें पता चले कि इसे उन्हें फिर से स्थापित करने की आवश्यकता नहीं है। (सभी उत्पन्न फाइलें फाइलें नहीं हैं .c, हालांकि, इसलिए मुझे पाठ तुलनाओं के बजाय द्विआधारी तुलना करने की आवश्यकता है।)

(नोट के रूप में: यह https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981562#8981762 पर मेरे द्वारा पूछे गए सवाल से आगे बढ़ा , जहाँ मैं कोशिश कर रहा था। इस ऑपरेशन को करने के लिए मैं जिस स्क्रिप्ट फ़ाइल का उपयोग कर रहा था, उसे गति देने के लिए, लेकिन मेरे साथ ऐसा होता है कि मुझे वास्तव में पूछना चाहिए कि क्या ऐसा करने का कोई बेहतर तरीका है कि मैं अपनी स्क्रिप्ट लिखूं - विशेष रूप से शेल में ऐसा करने के किसी भी सरल तरीके से। स्क्रिप्ट cmpफाइलों के हर जोड़े पर कुछ-कुछ आह्वान करेगी , और उन सभी प्रक्रियाओं को शुरू करने में बहुत लंबा समय लगता है।)


1
आप यह diff -qr dirA dirBदेखने के लिए उपयोग कर सकते हैं कि कौन सी फाइलें अद्वितीय हैं dirAऔर dirB, पश्चाताप से।

1
@ ब्रूक्स- मोस यह वास्तव में ccache के लिए अनुकूल काम है !
अकुलिच

3
@ यदि आप यूनिक फाइल्स को दिखाना चाहते हैं, तो आप अलग-अलग उपयोग कर सकते हैं, लेकिन अगर आप यह देखना चाहते हैं कि क्या बदल गया है तो उपयोग करें rsync -avncया लंबा रास्ता तय करें rsync --archive --verbose --dry-run --checksum
अकुलिच

जवाबों:


29

rsync शायद इसके लिए सबसे अच्छा उपकरण है। इस कमांड पर बहुत सारे विकल्प हैं इसलिए मैन पेज पढ़ें । मुझे लगता है कि आप --checksum विकल्प या theignore-times चाहते हैं


मुझे ध्यान देना चाहिए कि मैंने पहले ही कोशिश की थी, जिसमें कोई सफलता नहीं मिली। वे दोनों विकल्प केवल प्रभावित करते हैं कि क्या rsync एक प्रति करता है - लेकिन, जब वह प्रतिलिपि नहीं करता है, तब भी वह लक्ष्य फ़ाइल के संशोधन समय को स्रोत के समान (यदि -tविकल्प निर्दिष्ट किया गया है) या सिंक्रनाइज़ेशन समय पर अद्यतन करता है (यदि -tनिर्दिष्ट नहीं है)।
ब्रूक्स मूसा

4
@ बरोक मूसा: यह नहीं है। कम से कम मेरा संस्करण rsyncनहीं है। अगर मैं ऐसा करते हैं: mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* destहै, तो stat dest/aइसकी mtime पता चलता है और ctime 5 लोगों से अधिक उम्र के सेकेंड हैं src/a
angus

@angus: हुह। ठीक है, तुम सही हो। कुंजी का --checksumविकल्प प्रतीत होता है, और हालांकि linux.die.net/man/1/rsync में ऐसा कुछ भी नहीं है जिसका अर्थ है कि इसका कोई प्रभाव है कि क्या संशोधन तिथि अपडेट की गई है, फिर भी यह गंतव्य संशोधन तिथि को छोड़ देता है। अछूता। (दूसरी ओर, --ignore-timesविकल्प का यह प्रभाव नहीं होता है; इसके साथ संशोधन की तारीख अभी भी अपडेट है।) यह देखते हुए कि यह पूरी तरह से अनिर्दिष्ट लगता है, हालांकि, क्या मैं इस पर भरोसा कर सकता हूं?
ब्रूक्स मूसा

2
@BrooksMoses: मुझे लगता है कि आप इस पर भरोसा कर सकते हैं: rsync's वर्कफ़्लो है: 1) जांचें कि क्या फ़ाइल को अपडेट करने की आवश्यकता है; 2) यदि ऐसा है, तो फ़ाइल को अपडेट करें। --checksumविकल्प कहते हैं कि यह अद्यतन नहीं किया जा चाहिए, ताकि rsyncचरण 2 के लिए आगे नहीं बढ़ना चाहिए)।
enzotib

2
@BrooksMoses: --ignore-timesबिना --checksumहर फ़ाइल की नकल करेगा, और इसलिए टाइमस्टैम्प को भी अपडेट करें, भले ही फाइलें समान हों।
enzotib

13

आप ऐसा करने के लिए -uस्विच का उपयोग कर सकते हैं cp:

$ cp -u [source] [destination]

आदमी पृष्ठ से:

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

4
नमस्ते और साइट पर आपका स्वागत है। हम उम्मीद करते हैं कि उत्तर यहां कुछ अधिक महत्वपूर्ण होंगे। उदाहरण के लिए, आप इस विवरण को शामिल कर सकते हैं कि -uझंडा क्या करता है और यह कैसे काम करता है और यह कैसे ओपी को मदद करेगा। हालाँकि, इस विशेष मामले में, यह ओपी को मदद नहीं करेगा क्योंकि यह समान फ़ाइलों की नकल करेगा यदि वे नए थे और इसलिए अपने समय के टिकटों को बदल दें जो ठीक वही है जो ओपी बचना चाहता है।
terdon

1
समान ए पर एक टिप्पणी से जिसे पहले ही हटा दिया गया था: "यह काम नहीं करेगा क्योंकि यह समान फ़ाइलों को भी कॉपी करेगा, अगर स्रोत का टाइमस्टैम्प नया है (और इसलिए ओपी अनुरोध के खिलाफ गंतव्य का टाइमस्टैम्प अपडेट करें)।"
स्लम

इस सवाल का जवाब बिल्कुल नहीं है, लेकिन मैं अभी भी इसे उपयोगी पाया।
user31389

7

उपयोग करते समय rsync --checksum, "यदि बदला गया है तो" कॉपी करने का एक अच्छा सामान्य तरीका है, आपके विशेष मामले में एक और भी बेहतर समाधान है!

यदि आप अनावश्यक रूप से recompiling फ़ाइलों से बचना चाहते हैं, तो आपको ccache का उपयोग करना चाहिए जो कि इस उद्देश्य के लिए बनाया गया था! वास्तव में, यह न केवल आपके ऑटो-जनरेट किए गए फ़ाइलों के अनावश्यक recompiles से बचाएगा, जब भी आप इसे करते हैं make cleanऔर स्क्रैच से पुन: संकलित करते हैं, तो यह चीजों को भी गति देगा ।

आगे मुझे यकीन है कि आप पूछेंगे, "क्या यह सुरक्षित है?" ठीक है, हाँ, जैसा कि वेबसाइट बताती है:

क्या ये सुरक्षित है?

हाँ। एक संकलक कैश का सबसे महत्वपूर्ण पहलू हमेशा उसी आउटपुट का उत्पादन करना है जो वास्तविक संकलक उत्पादन करेगा। इसमें वास्तव में समान ऑब्जेक्ट फ़ाइलें प्रदान करना और वास्तव में समान संकलक चेतावनी शामिल है जो यदि आप वास्तविक संकलक का उपयोग करते हैं तो उत्पादन किया जाएगा। एकमात्र तरीका जो आपको यह बताने में सक्षम होना चाहिए कि आप ccache का उपयोग कर रहे हैं गति है।

और इसे अपने मेकफाइल की लाइन में एक उपसर्ग के रूप में जोड़कर इसका उपयोग करना आसान हैCC= (या आप सीमलिंक का उपयोग कर सकते हैं, लेकिन मेकफाइल का तरीका शायद बेहतर है)।


1
मुझे शुरू में गलत लगा और आप सुझाव दे रहे थे कि मैं ccache का उपयोग जनरेशन का हिस्सा करने के लिए कर रहा हूं, लेकिन अब मैं समझता हूं - आपका सुझाव यह था कि मैं बस सभी फाइलों को कॉपी करता हूं, और फिर निर्माण प्रक्रिया में ccache का उपयोग करता हूं, जिससे कि पुनर्निर्माण करने से बचता हूं नहीं बदला था। यह एक अच्छा विचार है, लेकिन यह मेरे मामले में अच्छा नहीं करेगा - मेरे पास सैकड़ों फाइलें हैं, आमतौर पर एक समय में केवल एक या दो ही बदलते हैं, और साइगविन के तहत चल रहा हूं, जहां प्रत्येक को देखने के लिए सैकड़ों ccache प्रक्रियाओं को शुरू करना है फ़ाइल में कई मिनट लगेंगे। फिर भी, उत्कीर्ण क्योंकि यह ज्यादातर लोगों के लिए एक अच्छा जवाब है!
ब्रूक्स मूसा

नहीं, मैं यह सुझाव नहीं दे रहा था कि आप सभी फाइलों को कॉपी करें, बल्कि आप अपनी .c फाइलों को केवल ऑटोगेनेरेट कर सकते हैं (कॉपी स्टेप को हटा दें और उन्हें सीधे लिखें)। और फिर बस ccache का उपयोग करें। मुझे नहीं पता कि सैकड़ों ccache प्रक्रियाओं को शुरू करने से आपका क्या मतलब है ... यह सिर्फ gcc के चारों ओर एक हल्के वजन का आवरण है जो काफी तेज है और आपके प्रोजेक्ट के अन्य भागों को भी पुन: निर्माण करेगा। क्या आपने इसका उपयोग करने की कोशिश की है? मैं आपकी कॉपी-विधि बनाम ccache का उपयोग करने के बीच के समय की तुलना देखना चाहूंगा। आप वास्तव में, दोनों के लाभों को प्राप्त करने के लिए दो तरीकों को जोड़ सकते हैं।
एकुलिच

1
ठीक है, ठीक है, मैं अब नकल के बारे में समझता हूं। स्पष्ट करने के लिए, मेरा मतलब यह है: यदि मैं फ़ाइलों को जगह में उत्पन्न करता हूं, तो मुझे ccache file.c -o file.oकई बार कॉल या समकक्ष, कई सौ बार करना होगा क्योंकि कई सौ file.cफाइलें हैं। जब मैं ऐसा कर रहा था cmp, इसके बजाय ccache, इसमें कई मिनट लगे - और cmpयह जितना हल्का है ccache। समस्या यह है कि, सिग्विन पर, एक प्रक्रिया शुरू करना गैर-नगण्य समय लगता है, यहां तक ​​कि पूरी तरह से तुच्छ प्रक्रिया के लिए भी।
ब्रूक्स मूसा

1
एक डाटापॉइंट के रूप में, for f in src/*; do /bin/true.exe; done30 सेकंड लगते हैं, इसलिए हाँ। वैसे भी, मैं अपने विंडोज-आधारित संपादक को पसंद करता हूं, और इस तरह के समय के मुद्दे से अलग सिगविन मेरे वर्कफ़्लो के साथ काफी अच्छी तरह से काम करता है, क्योंकि अगर मैं बिल्ड सर्वर पर अपलोड नहीं कर रहा हूं तो स्थानीय रूप से चीजों का परीक्षण करने के लिए हल्का स्थान है। एक ही OS में मेरा शेल और मेरा एडिटर होना उपयोगी है। :)
ब्रूक्स मूसा

1
यदि आप अपने विंडोज-आधारित संपादक का उपयोग करना चाहते हैं, तो आप बहुत आसानी से साझा किए गए फ़ोल्डर के साथ कर सकते हैं यदि आप अतिथि जोड़ स्थापित करते हैं ... लेकिन हे, अगर सिगविन आपको सूट करता है, तो मैं कौन हूं किसी भी अलग से कहने के लिए? यह सिर्फ इस तरह से अजीब हुप्स के माध्यम से कूदने के लिए एक शर्म की बात लगती है ... और सामान्य रूप से संकलन एक वीएम में भी तेज होगा।
aculich

3

यह वही करना चाहिए जो आपको चाहिए

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

कहा पे:

  • x आपका अपडेटेड / नया फोल्डर है
  • y वह गंतव्य है जिसे आप कॉपी करना चाहते हैं
  • awk कमांड से प्रत्येक पंक्ति का दूसरा तर्क लेगा (हो सकता है कि आपको अंतरिक्ष के साथ फ़ाइल नाम के लिए कुछ अतिरिक्त सामान की आवश्यकता होगी - अब इसे आज़मा नहीं सकते)
  • xargs -J% उचित स्थान पर cp में फ़ाइल नाम सम्मिलित करेगा

1
-1 क्योंकि यह अत्यधिक जटिल है, गैर-पोर्टेबल है ( -Jजीएनयू xargs के साथ यह bsd- विशिष्ट है -I), और सही ढंग से काम नहीं करता है यदि फ़ाइलों का एक ही सेट पहले से ही दोनों स्थानों में मौजूद नहीं है (यदि मैं touch x/booतब grep मुझे देता है Only in ./x: booजो पाइपलाइन में त्रुटियां पैदा करता है)। काम के लिए बनाए गए उपकरण का उपयोग करें, जैसे rsync --checksum
अकुलिच

या बेहतर अभी तक, इस विशिष्ट मामले के लिए ccache का उपयोग करें
अकुलिच

+1 क्योंकि इसकी जानी-मानी आज्ञाओं का एक सेट जिसे मैं समान कार्यों पर उपयोग करने के लिए तोड़ सकता हूं (एक अलग काम करने के लिए यहां आया था), फिर भी rsync इस विशेष कार्य के लिए बेहतर हो सकता है
ntg

3

मैं इसके पक्ष में एकरूपता का उपयोग करना पसंद करता हूं rsyncक्योंकि यह कई मास्टर्स का समर्थन करता है, पहले से ही मेरे ssh कीज़ को सेटअप करने और अलग से वीपीएन करने के लिए।

इसलिए केवल एक मेजबान के मेरे क्रैस्टैब में मैंने उन्हें हर 15 मिनट में सिंक्रनाइज़ करने दिया:

* (15 * * * * * -z "$ (pidof unison)"] और& (टाइमआउट 25 m unison -sortbysize -ui text -batch -times / home / master ssh: //192.1.1.1.12//home/master -path dev -logfile /tmp/sync.master.dev.log) और> /tmp/sync.master.dev.log

फिर मैं दोनों तरफ विकसित हो सकता हूं और परिवर्तन प्रचारित करेंगे। वास्तव में महत्वपूर्ण परियोजनाओं के लिए मेरे पास 4 सर्वर हैं जो एक ही पेड़ को दर्शाते हैं (क्रॉन से 3 रन एकसमान, एक को इंगित नहीं करता है)। वास्तव में, Linux और Cygwin को मिलाया जाता है - सिवाय इसके कि साइबर स्पेस के बाहर win32 में सॉफ्ट लिंक्स से समझदारी की उम्मीद नहीं है।

यदि आप इस मार्ग पर जाते हैं, तो प्रारंभिक दर्पण को खाली स्थान पर बिना -batch, यानी

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

बेशक, बैकअप फ़ाइलों, अभिलेखागार, आदि की उपेक्षा करने के लिए एक विन्यास है।

 ~/.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

मैंने उस पर ध्यान दिया, लेकिन मुझे एक unisonविकल्प नहीं मिला, जिसका अर्थ है "फ़ाइल-अंतिम-संशोधित तिथियों को अपडेट न करें"। वहाँ एक है? अन्यथा, यह एक पूरी तरह से अलग समस्या का एक शानदार जवाब है।
ब्रूक्स मूसा

1
-timesमेरे लिए वही करता है। यूनिसन में एक ड्राई-रन मोड भी है, मुझे लगता है।
मार्कोस

खैर, सेटिंग times=false(या बंद -times) ऐसा होगा। मुझे नहीं पता कि मैंने पहले प्रलेखन में इसे कैसे याद किया। धन्यवाद!
ब्रूक्स मूसा 23

मदद करने में खुशी। जब मैं मॉडिम्स, परमिशन और सॉफ्ट लिंक्स जैसी चीजों को संरक्षित करने की बात करता हूं तो मैं एक स्टिकलर हूं। अक्सर अनदेखी
मार्कोस

1

जबकि rsync --checksumसही उत्तर, ध्यान दें कि यह विकल्प से संगत नहीं है --times, और कहा कि --archiveशामिल --timesहै, इसलिए यदि आप चाहते हैं rsync -a --checksum, क्या तुम सच में करने की जरूरत है rsync -a --no-times --checksum


Pat असंगत ’कहने का क्या मतलब है?
ओव

"सही उत्तर है" से आपका क्या तात्पर्य है?
thoni56
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.