प्रत्येक फ़ाइल के लिए हार्डलिंक का उपयोग करके किसी निर्देशिका की प्रतिलिपि कैसे बनाएं


52

मैं एक निर्देशिका ट्री की "कॉपी" बनाना चाहता हूं जहां प्रत्येक फ़ाइल मूल फ़ाइल के लिए एक हार्डलिंक है

उदाहरण: मेरे पास एक निर्देशिका संरचना है:

dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3

यहां अपेक्षित परिणाम है, निर्देशिका पेड़ की "कॉपी" जहां प्रत्येक फ़ाइल मूल फ़ाइल के लिए एक हार्डलिंक है:

dirB/            #  normal directory
dirB/file1       #  hardlink to dirA/file1
dirB/x/          #  normal directory
dirB/x/file2     #  hardlink to dirA/x/file2
dirB/y/          #  normal directory
dirB/y/file3     #  hardlink to dirA/y/file3

जवाबों:


50

लिनक्स पर (जीएनयू के साथ और अधिक सटीक रूप busyboxसे cpऔर आमतौर पर सिस्टम के रूप में पाया जाता है जिसमें लिनक्स कर्नेल के रूप में होता है) और हाल ही में फ्रीबीएसडी, यह इस प्रकार है:

cp -al dirA dirB

अधिक पोर्टेबल समाधान के लिए, स्टीफन चेज़लस द्वारा पैक्स और सीपियो का उपयोग करके उत्तर देखें


ध्यान दें कि pax, FreeBSD पर, cp -aहार्डलिंक सिमलिंक को पसंद नहीं करता है।
स्टीफन चेज़लस

ध्यान रखें कि हार्ड लिंक अलग फाइलसिस्टम माउंट में काम नहीं करते हैं।
डेव

24

POSIXly, आप विकल्प के paxसाथ रीड + राइट मोड में उपयोग करेंगे -l:

pax -rwlpe -s /A/B/ dirA .

( -peफाइलों की सभी संभावित विशेषताओं को सुरक्षित रखता है (इस मामले में केवल निर्देशिकाएं) जो कॉपी की जाती हैं, जैसे कि GNU cpकी -aहै)।

अब, हालांकि मानक , वह आदेश बहुत पोर्टेबल नहीं है ।

सबसे पहले, कई GNU / लिनक्स-आधारित सिस्टम paxडिफ़ॉल्ट रूप से शामिल नहीं होते हैं (भले ही यह एक गैर-वैकल्पिक POSIX उपयोगिता हो)।

फिर, कई कार्यान्वयन के साथ बग और गैर-अनुरूपता उस कोड के साथ कई मुद्दों का कारण बनते हैं।

  • बग के कारण, Solaris 10 pax(कम से कम) के -rwlसाथ संयोजन में उपयोग करते समय काम नहीं करता है -s। किसी कारण से, ऐसा लगता है कि यह मूल और प्रतिलिपि किए गए पथ दोनों के प्रतिस्थापन को लागू करता है। इसलिए, इसके link("dirB/file", "dirB/file")बजाय , यह कुछ करने की कोशिश करेगा link("dirA/file", "dirB/file")
  • FreeBSD पर, paxटाइप सीमलिंक (POSIX द्वारा अनुमत व्यवहार) की फ़ाइलों के लिए हार्डलिंक नहीं बनाता है । इतना ही नहीं, लेकिन यह सिम्बलिंक के लक्ष्यों के प्रतिस्थापन ( पोसिक्स द्वारा अनुमति नहीं दिया गया व्यवहार ) पर भी लागू होता है । तो उदाहरण वहाँ एक है कि अगर के लिए foo -> AAमें सिमलिंक dirA, यह हो जाएगा foo -> BAमें dirB

इसके अलावा, यदि आप ऐसा ही करना चाहते हैं, लेकिन मनमाने फ़ाइल पथों के साथ जिनकी सामग्री में संग्रहीत है, $srcऔर $dstयह महसूस करना महत्वपूर्ण है कि यह अंदर pax -rwl -- "$src" "$dst"की पूर्ण निर्देशिका संरचना बनाता $srcहै $dst(जिसका अस्तित्व है और एक निर्देशिका बनना है)। उदाहरण के लिए, यदि $srcहै foo/bar, तो $dst/foo/barबनाया गया है।

यदि इसके बजाय, आप इसकी $dstएक प्रति बनना चाहते हैं, तो $srcशायद यह करना सबसे आसान है:

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")

(जो ऊपर बताई गई अधिकांश समस्याओं के आसपास भी काम करेगा, लेकिन यदि $dstनई वर्णमाला में समाप्त होने का पूर्ण मार्ग है तो विफल हो जाएगा )।

अब यह GNU / Linux सिस्टम पर मदद नहीं करेगा जहाँ कोई नहीं है pax

यह ध्यान रखना दिलचस्प है कि paxPOSIX द्वारा tarऔर cpioकमांड की विशेषताओं को मर्ज करने के लिए बनाया गया था ।

cpioPOSIX आविष्कार के विपरीत एक ऐतिहासिक यूनिक्स कमांड (1977 से) है, और एक GNU कार्यान्वयन भी है (एक नहीं pax)। तो भले ही यह एक मानक कमांड नहीं है (हालांकि यह SUSv2 में था), यह अभी भी बहुत आम है, और इसमें उन विशेषताओं का एक मुख्य समूह है, जिन पर आप आमतौर पर भरोसा कर सकते हैं।

के बराबर pax -rwlहोगा cpio -pl। हालाँकि:

  1. cpio तर्कों पर विरोध के रूप में इनपुट फ़ाइल की सूची लेता है (newline सीमांकित जिसका अर्थ है कि newline वर्णों के साथ फ़ाइल नाम समर्थित नहीं हैं)
  2. सभी फ़ाइलें (आमतौर पर आप इसे के उत्पादन को खिलाने के लिए निर्दिष्ट किया जा करने के लिए है find( findऔर cpio) एक ही लोगों द्वारा संयुक्त रूप से विकसित किया गया)।
  3. मेटाडेटा संरक्षित नहीं है (कुछ cpioकार्यान्वयन में कुछ को संरक्षित करने के विकल्प हैं, लेकिन कुछ भी नहीं पोर्टेबल)।

तो इसके साथ cpio:

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")

ऐसा लगता है कि -s / A / B / मेरे उदाहरण के लिए विशिष्ट है। यदि स्रोत निर्देशिका नाम और लक्ष्य निर्देशिका नाम चर $ sourcedir और $ targetdir थे तो आप यह कैसे करेंगे?
गुडमुंडुर ओरन

@GudmundurOrn, संपादन देखें।
स्टीफन चेज़लस

मैं ओएस एक्स पर इस कमांड को चलाता हूं और बस एक त्रुटि संदेश प्राप्त करता है "पैक्स: लिंक फ़ाइल में असमर्थ ।/a.txt खुद के लिए"। मैंने आपके आदेश का शाब्दिक उपयोग किया है, बस स्रोत निर्देशिका को वास्तविक नाम के साथ बदल रहा है, / A / B और अंतिम डॉट के रूप में है। क्या मैं कुछ गलत समझ रहा हूँ?
db

@db, के साथ -s /A/Bबदलता है जो बन जाता है । यदि आपके स्रोत निर्देशिका का नाम नहीं है , तो वह इसे स्वयं लिंक करेगा (लिंक)। संभवतः बेहतर दृष्टिकोण के लिए बाकी उत्तर भी देखें। ABdirAdirBA
स्टीफन चेजलस


2

यदि आप उस कॉपी-विथ-हार्डलिंक सुविधा की तलाश कर रहे हैं, जिसमें आपकी फ़ाइलों का स्नैपशॉट या बैकअप (सभी या कुछ भाग) मौजूद हैं rsnapshot


1
यह तो दिलचस्प है। लेकिन मुझे लगता है कि हार्ड-लिंक केवल एक अच्छा स्नैपशॉट तंत्र हैं अगर फाइलें संशोधित नहीं होंगी। सही?
गुडमुंडुर ओरन

@ गुडमुंडुर ऑर्न; यह सही है। मेरे उत्तर में उल्लिखित टूल एक नया स्नैपशॉट बनाएगा, जिसमें फाइलें विशिष्ट हैं; अर्थात मौजूदा (अनमॉडिफाइड) फाइलें हार्डलिंक के रूप में बनाई जाएंगी और नई फाइलों (या मौजूदा फाइलों के संशोधित संस्करण) को नई फाइलों के साथ बनाया जाएगा। इसलिए परिणाम में आपको कम से कम अतिरेक होगा।
Janis

0

@ गुडमुंडुर-ऑर्न का जवाब सही है, लेकिन यदि आप लिनक्स पर BtrFS पर cp a --reflink=auto dirA dirBहैं, तो चाल को करना चाहिए, अंतर के साथ फाइलें वास्तव में अलग हैं और एक को बदलने से दूसरे को नहीं बदलता है। आप cp -cAPFS के साथ मैक पर अधिकतर समान प्राप्त कर सकते हैं ( autoयदि संभव नहीं हो तो पूरी नकल -cकरेंगे , विफल हो जाएंगे)।

कोई भी फ़ाइल सिस्टम ऐसा करने में सक्षम होना चाहिए, लेकिन विक्रेताओं ने एक मानक कमांड लाइन विकल्प पर सहमति नहीं दी है।

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