लिनक्स में डायरेक्टरी को कॉपी करते समय -r पुनरावर्ती क्यों आवश्यक है?


47

मेरा प्रश्न यह है कि -rनिर्देशिका की प्रतिलिपि बनाते समय (पुनरावर्ती) ध्वज का उपयोग करना क्यों आवश्यक है ? यानी, ऐसा क्यों करें:

$ cp -r dir1 copyDir1

निर्देशिका की प्रतिलिपि बनाते समय मैं यह व्यवहार कब नहीं करना चाहूंगा?

वास्तव में "डिफ़ॉल्ट" व्यवहार की निर्देशिका की पुनरावर्ती प्रतिलिपि नहीं है; व्यवहार हम लगभग हर समय चाहते हैं?

ऐसा महसूस होता है कि यह एक शानदार झंडा है।


क्या आपको इसमें फ़ाइलों और फ़ोल्डर की प्रतिलिपि बनाने की आवश्यकता नहीं होगी?
QuyNguyen2013

अगर आपको लगता है कि यह एक सुधार होगा तो आप डेवलपर्स चैनल पर इस अनुरोध को रद्द कर सकते हैं। अन्यथा यह शायद बहुत पहले ही प्रोग्राम किया गया था।
ब्लॉगर

@ ब्लॉगर यह बहुत पहले ही प्रोग्राम किया गया था, लेकिन एक कारण के लिए। मतलब अगर कोई कमांड लाइन के माहौल में बुनियादी काम करना चाहता है, तो उनका काम केवल उतना ही आसान होना चाहिए जितना कि सिस्टम की विफलता से बचना कठिन है। मतलब कुछ अच्छे कारण हैं कुछ कमांड लाइन उपयोगकर्ता इंटरैक्शन कन्वेंशन मौजूद हैं। मैं अपने उत्तर में इस अवधारणा पर विस्तार करता हूं।
जाकेगोल्ड 20


वही जाता हैrm

जवाबों:


58

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

तो कमांड लाइन के नजरिए से, ऐसा करना:

$ cp dir1 copyDir1

मूल रूप से नामित फ़ाइल की प्रतिलिपि बनाई जाएगी, जिसका नाम dir1एक नई फ़ाइल है copyDir1। और जहां तक ​​फाइल सिस्टम का सवाल है, तो dir1यह सिर्फ एक फाइल है; तथ्य यह है कि यह एक "निर्देशिका" केवल तब स्पष्ट होगा जब फाइल सिस्टम वास्तव में dir1यह देखने के लिए जांचता है कि वास्तव में बिट्स का ढेर क्या है।

-rझंडा फ़ाइल / निर्देशिका वृक्ष नीचे रिकर्सिवली रोल करने के लिए फाइल सिस्टम बताता है और किसी भी और सभी सामग्री है कि एक नई जगह के लिए एक उस फ़ाइल की "बच्चा" हो सकता है नकल।

अब ऐसा क्यों है कि यह अतिरेक या अतिरेक लग सकता है, यह वास्तव में फ़ाइल सिस्टम से निपटने के ऐतिहासिक तरीकों के लिए आता है। साथ ही एक ऐसी प्रणाली का निर्माण करना जो सभी प्रकार की उपयोगकर्ता संबंधी त्रुटियों से सुरक्षित हो; आकस्मिक और साथ ही जानबूझकर।

मतलब, मान लीजिए कि आपके पास ~/binअपनी होम डायरेक्टरी में एक फाइल है जिसे आप कॉपी करना चाहते हैं लेकिन गलती से छोड़ दिया गया है ~-क्योंकि आप एक इंसान हैं और गलतियाँ करते हैं - तो बस /binइस तरह से:

cp /bin/ ~/copy_of_bin

झंडे /binकी आवश्यकता के साथ संयुक्त निर्देशिका होने के "सुरक्षा जाल" के साथ -rआप गलती से उस सिस्टम के पूरे बाइनरी रूट की नकल करने से बचेंगे जो आप अपने घर की निर्देशिका में हैं। यदि वह सुरक्षा जाल मौजूद नहीं था, तो एक मामूली या संभवतः बड़ी दुर्घटना होगी।

यहाँ तर्क दिया जा रहा है कि दिनों में पूर्व-जीयूआई (ग्राफिकल यूजर इंटरफेस) तार्किक / व्यवहारिक सम्मेलनों को सेट करने की आवश्यकता है ताकि उपयोगकर्ता द्वारा बनाई गई गलतियाँ हो सकती हैं जो सिस्टम को मार सकती हैं। और -rझंडे का उपयोग करना अब उनमें से एक है।

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

लेकिन पाठ-आधारित इंटरफेस के दायरे के मामले में, उस दुनिया के भीतर "उपयोगकर्ता अनुभव" के बहुत सारे मूल रूप से तार्किक और hueristic- आधारित सड़क धक्कों हैं जो उपयोगकर्ता को जांच में रखने में मदद करते हैं ताकि संभावित आपदा को रोका जा सके।

इसी तरह लिनक्स / यूनिक्स फाइल सिस्टम में डिफ़ॉल्ट रूप से 777अनुमतियाँ और sudoअधिकार सेट नहीं होते हैं और जब उपयोगकर्ता 777अनुमतियाँ सेट करता है या वास्तविक sudoअधिकार प्राप्त करता है तो वास्तविक सिस्टम प्रशासक कैसे विचलित होते हैं। ये बुनियादी चीजें हैं जो सिस्टम को स्थिर और "उपयोगकर्ता प्रमाण" जितना संभव हो सके सुनिश्चित करने के लिए करती हैं; शॉर्ट-सर्किट के कारण उन सम्मेलनों में भाग लेने वाले किसी भी व्यक्ति को यह जानने के बिना भी उनके सिस्टम को नुकसान होगा।

अतिरिक्त जानकारी: यूनिक्स स्टैक एक्सचेंज साइट पर यहां एक और जवाब एक अच्छी व्याख्या देता है कि किसी निर्देशिका की गैर-पुनरावर्ती प्रतिलिपि समस्याग्रस्त क्यों है; जोर मेरा है।

खैर, -R फ्लैग के बिना, केवल फाइलों को कॉपी करना संभव है, क्योंकि यह असामान्य है कि कोई व्यक्ति गैर-पुनरावर्ती रूप से एक निर्देशिका की प्रतिलिपि बनाना चाहता है: एक गैर-पुनरावर्ती प्रतिलिपि का परिणाम सीधे निर्देशिका के लिए दूसरे नाम में होगा, सीधे इंगित करने के लिए। एक ही निर्देशिका संरचना। क्योंकि शायद ही कभी लोग क्या चाहते हैं, और वास्तव में एक अलग कार्यक्रम है जो ऐसा करता है (ln), निर्देशिका की एक गैर-पुनरावर्ती प्रतिलिपि की अनुमति नहीं है।

इसलिए यदि कोई निर्देशिका वास्तव में एक फ़ाइल है जिसके अंदर इनोड आइटम हैं, तो उस फ़ाइल की एक सीधी प्रतिलिपि बनाने से यह बराबर होगा कि एक कड़ी कैसे काम करेगी। जो किसी को नहीं चाहिए।


19
मुझे व्यक्तिगत रूप से लगता है कि इसका "संरक्षण" पहलू गंध परीक्षण पास नहीं करता है। कुछ मानव बस के रूप में आसानी से टाइप कर सकते हैं cp -r /binके रूप में cp-r ~/bin। ध्वज स्वयं गलतियों को रोकता नहीं है या जरूरी नहीं है कि किसी को भी सावधान रहना चाहिए। यदि आप गलतियों को रोकना चाहते हैं, तो cp कमांड केवल प्रश्न में नोड को आसानी से देख सकता है और एक संकेत प्रदान कर सकता है, कुछ इस तरह से "यह एक निर्देशिका है, क्या आप निर्दिष्ट स्थान पर सभी सामग्रियों को कॉपी करना चाहते हैं (y / n)? " यही कारण है कि हो सकता है सुरक्षा तंत्र । निर्देशिकाओं के लिए आवश्यक -r कुछ से अधिक नीचे कोड का ब्लोट रखता है।
JDL

12
मैनहोल के साथ खराब सादृश्य। जैसा कि @JDL ने कहा, प्रश्न में ध्वज पथ में एक टाइपो को रोकने के लिए कुछ भी नहीं करता है। मैं एक कारण के रूप में अन्य आदेशों के साथ संगतता को स्वीकार करने में खुशी होगी, लेकिन मुझे लग रहा है कि असली कारण "यह है कि यह पहले कैसे लिखा गया था और अब इतनी सारी चीजें उस व्यवहार पर भरोसा करती हैं, इसे बदलना असंभव है"।
बेसिक

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

2
अगर मैं गलत नहीं हूँ, -r एक GNU एक्सटेंशन था - मुझे नहीं लगता कि ऐतिहासिक UNIX cp में एक पुनरावर्ती प्रतिलिपि थी - और कमांड rsync का कारण था ।
मेई

2
@JakeGould मैं बुनियादी अवधारणाओं को समझता हूं। मैं, हालांकि, इस विचार के खिलाफ तर्क देता हूं कि प्रश्न में कमांड पर एक-आर ध्वज किसी भी अतिरिक्त सुरक्षा प्रदान करता है। मेरे अनुभव से, कमांड लाइन लाइनक्स कमांड ऐतिहासिक रूप से स्वाभाविक रूप से असुरक्षित हैं। ओवरटाइम में सुरक्षा को जोड़ दिया गया है, अगर बिल्कुल भी। लिनक्स डिजाइन में निहित सुरक्षा अनुमतियाँ प्रणाली से आती हैं और रूट के रूप में चलती हैं। रूट के रूप में नहीं चलना भी एक ऐसी चीज है जो एक डिजाइन की तुलना में एक कन्वेंशन से अधिक है। अधिवेशन ज्यादातर नए लिनक्स इंस्टॉलर में समर्थित है, लेकिन हमेशा नहीं था।
JDL

19

यह बहुत सच है कि यह वह व्यवहार है जो हम लगभग हर समय चाहते हैं। हालांकि, इसका मतलब यह नहीं है कि पुनरावर्ती रूप से नकल करना डिफ़ॉल्ट व्यवहार होना चाहिए।

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

यहां पहेली का मुख्य टुकड़ा यह महसूस कर रहा है कि cpनिर्देशिकाओं की प्रतिलिपि नहीं करता है - cpप्रतियां फाइलें (और केवल फाइलें)। यदि आप किसी निर्देशिका की प्रतिलिपि बनाना चाहते हैं, तो प्रत्येक निर्देशिका पर फ़ाइलों की प्रतिलिपि बनाने के लिए, cp स्वयं को पुनरावर्ती रूप से कॉल करता है

बेशक, "प्रतिलिपि निर्देशिकाओं" और "नकल फ़ाइलों की पुनरावृत्ति" के बीच का अंतर उपयोगकर्ता के दृष्टिकोण से बिल्कुल कुछ भी नहीं है, लेकिन इस इंटरफ़ेस के होने से कार्यान्वयन सरल रहने में मदद मिलती है

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

एक और फायदा यह है कि -rयूजर को यह समझने में भी मदद मिलती है कि इंटरफेस के नीचे क्या हो रहा है। इसका एक अच्छा दुष्परिणाम यह है कि पुनरावर्ती ऑपरेशन की अवधारणा को सीखने से आपको कुछ ऐसे काम मिलेंगे जब आप अन्य उपकरणों के बारे में जानेंगे जो इसका समर्थन करते हैं (जैसे grep, उदाहरण के लिए)


कुछ लोग निश्चित रूप से आपको बताएंगे कि उपयोगकर्ता के लिए कार्यान्वयन विवरणों को उजागर करना बुरा है , और यह कि अधिक सुविधाएँ होना अच्छा है । यहाँ मेरा इरादा केवल इस व्यवहार के औचित्य को समझा रहा है, इसलिए मैं किसी भी तरह से बहस करने की कोशिश नहीं करूँगा।


2
+1 "... एक काम करो और इसे अच्छे से करो ..." इसके लिए धन्यवाद!
जाकगोल्ड

5

निर्देशिकाओं के साथ सहभागिता सुनिश्चित करता है कि आप जानते हैं कि आप एक निर्देशिका के साथ बातचीत कर रहे हैं और केवल एक फ़ाइल नहीं।

उदाहरण के लिए:

$ tree
.
└── folder1
    └── sub1
        └── subsub1

3 directories, 0 files
$
$ cp folder1/ folder2
cp: folder1/ is a directory (not copied).
$
$ mkdir blah
$ cp blah/ blah2
cp: blah/ is a directory (not copied).
$ rm blah/
rm: blah/: is a directory

इसलिए, यदि आप किसी फ़ोल्डर की सफल प्रतिलिपि बनाना चाहते हैं, क्योंकि यह फ़ोल्डर को संदर्भित करने और फ़ोल्डर को संदर्भित करने से संबंधित दोनों वस्तुओं का अर्थ है, तो आपको इसका इलाज करना होगा जैसे कि इसकी फ़ाइलों का एक संग्रह:

$ cp -r folder1/ folder2
$ rm -rf folder1

3

डिफ़ॉल्ट को बदलने का परिणाम यह होगा कि हजारों शेल स्क्रिप्ट टूट जाएंगे। यह अच्छी तरह से ज्ञात डिफ़ॉल्ट व्यवहार के लिए POSIX और SUS आवश्यकताओं की ओर जाता है।

इसका कारण विभिन्न एसटीआई शाखाओं में cp, ln और mv कमांड्स (सभी पुराने UNIX सिस्टमों पर सभी समान बाइनरी) का ऐतिहासिक विकास है। जब -rदिखाई दिया (जल्दी cpनिर्देशिका को कॉपी करने का विकल्प नहीं था, तो यहां एक प्रारंभिक सीपी मैन पेज है-r या इसके बिना -R), विशेष फाइल, सिमिलिंक और फाइलसिस्टम की अन्य योनियों को संभालने में विभिन्न अंतर थे।

से ओपन समूह बेस विनिर्देशों अंक 7 :

इस मानक के पुराने संस्करणों में फ़ाइल पदानुक्रम की प्रतिलिपि करने के लिए -r विकल्प के लिए समर्थन शामिल था। -R विकल्प बीएसडी और बीएसडी-व्युत्पन्न प्रणालियों पर ऐतिहासिक अभ्यास है। यह विकल्प अब POSIX.1-2008 द्वारा निर्दिष्ट नहीं है, लेकिन कुछ कार्यान्वयन में मौजूद हो सकता है। -R विकल्प को -r विकल्प के करीबी पर्यायवाची के रूप में जोड़ा गया, POSIX.1-2008 की इस मात्रा में अन्य सभी विकल्पों के साथ संगति के लिए चुना गया है जो पुनरावर्ती निर्देशिका वंश को करते हैं।

नियमित और निर्देशिका के अलावा फ़ाइल प्रकारों के cR द्वारा -R और हटाए गए -r विकल्प के बीच अंतर उपचार में है। यह कार्यान्वयन-परिभाषित था कि कैसे - विकल्प ने विशेष फाइलों को दोनों ऐतिहासिक कार्यान्वयनों की अनुमति देने के लिए इलाज किया और जो समर्थन के लिए चुने गए -r के समान -R के साथ-साथ POSIX.1-2008 के इस वॉल्यूम द्वारा परिभाषित किया गया। ऐतिहासिक कारणों से, मूल-आर ध्वज ने विशेष फ़ाइलों को नियमित फ़ाइलों से अलग नहीं किया, लेकिन हमेशा फ़ाइल को पढ़ा और इसकी सामग्री की प्रतिलिपि बनाई। इसमें विशेष फ़ाइल प्रकारों की उपस्थिति में स्पष्ट समस्याएं थीं; उदाहरण के लिए, चरित्र उपकरण, FIFO और सॉकेट।

वास्तव में आप अभी भी कुछ लोगों को नियमित रूप से उपयोग करते देखेंगे:

cd dir1 ; tar -cf - . | (cd dir2 ; tar -xpf -)

क्योंकि वे इस बात पर भरोसा नहीं करते हैं कि cp -rकार्यान्वयन के साथ वे एक मनमानी मशीन पर उपयोग किए जाते हैं; या इसलिए कि वे tarव्यवहार चाहते हैं।


3

हो सकता है कि यह आज सब-यूटीआई हो, लेकिन यह यूनिक्स के डिजाइन के दौरान 1970 के आसपास कुछ समय का निर्णय था, जब डिस्क काफी महंगी थी। लाखों शेल स्क्रिप्ट इस तरह से काम करने पर निर्भर करती हैं, और इसे बदलने में बहुत देर हो चुकी है।

मूल डिज़ाइन जानकारी के लिए यह लेख देखें ।


3

-rध्वज का एक स्पष्ट लाभ यह है कि आप स्रोत निर्देशिका में cp * /target/dirकेवल सभी फाइलों को लक्ष्य निर्देशिका में कॉपी कर सकते हैं , (चेतावनी के साथ यद्यपि) सभी निर्देशिकाओं में निहित हैं। cp -r * /target/dirसब-के-सब सहित, सब-कॉपीज़ को कॉपी करेगा।


2

आपको इस ध्वज की आवश्यकता तभी होती है जब यह फाइलों और निर्देशिकाओं कीcp नकल करने के लिए एक कमांड हो और केवल निर्देशिका ही न हो।

यदि निर्देशिकाओं की प्रतिलिपि के लिए एक विशेष आदेश था, तो "डिफ़ॉल्ट" व्यवहार निश्चित रूप से एक पुनरावर्ती प्रतिलिपि होगा।


1
समझ में आता है। लेकिन कोई ऐसे डायरेक्टरी की नकल क्यों करेगा, जिसमें कम से कम एक फाइल न हो? क्यों नहीं बस का उपयोग करें mkdir?
जेकगोल्ड

1
@JakeGould शायद क्योंकि वे स्वामित्व और अनुमति को संरक्षित करने की आवश्यकता हो सकती है?
रुस्लान

1

जैसा कि दूसरों ने उल्लेख किया है, एक निर्देशिका मूल रूप से केवल एक अन्य प्रकार की फ़ाइल है (एक नियमित फ़ाइल के विपरीत), जिसमें आमतौर पर "(") अन्य फाइलें होती हैं। इसमें उपनिर्देशिकाएँ शामिल हो सकती हैं, जिनके लिए यह लागू होता है ...

इसलिए यदि आप एक निर्देशिका (उपयोगकर्ता के परिप्रेक्ष्य) की नकल कर रहे हैं, तो आप वास्तव में फ़ाइलों का एक गुच्छा (फाइल सिस्टम के परिप्रेक्ष्य) (नियमित फाइलें, निर्देशिका फाइलें, प्रतीकात्मक लिंक, ...) की नकल कर रहे हैं और प्रत्येक निर्देशिका फ़ाइल के लिए, आप पुनरावृत्ति कर रहे हैं कि प्रक्रिया। चूंकि एक निर्देशिका की प्रतिलिपि बनाना एक पुनरावर्ती प्रक्रिया की परिभाषा है, इसलिए cp का तर्क कहा जाता है --recursive

यह निश्चित रूप से, आपके उपयोगकर्ता वातावरण में एक कमांड शॉर्टकट बनाने के लिए बहुत आसान है (इसे स्थायी रूप से उपलब्ध कराने के लिए इसे अपने .profile / .bashrc फ़ाइल में डालें):

alias cpr='cp -r'

या शायद बेहतर:

alias cpa='cp -av'

इस तरह, आप एक निर्देशिका का उपयोग करके कॉपी कर सकते हैं cpa dir1 copyDir1और यह न केवल मुद्रित होगा जो कॉपी किया जा रहा है, बल्कि फ़ाइल अनुमतियां भी लागू करेगा।

और जब से किसी ने उल्लेख किया है कि cp सैद्धांतिक रूप से यह पता लगा सकता है कि स्रोत फ़ाइल एक निर्देशिका है और पूछें कि क्या इसे पुनरावर्ती रूप से कॉपी करना चाहिए, तो यहां एक त्वरित सुझाव दिया गया है:

cp()
{
    if [ ! -e "$1" ]; then
        echo missing source file
        return 1
    fi
    arg="-d --preserve=all -v"
    if [ -d "$1" ]; then
        read -p "Copy directory recursively? " -n 1 -r
        if [ "$REPLY" == "y" ]; then
            arg="$arg -r"
        fi
        echo
    fi
    /usr/bin/cp $arg "$@"
}

यह सिर्फ एक सस्ता सीपी रैपर है। यह हमेशा सभी मेटा डेटा को संरक्षित करता है (यानी, प्रतियां फ़ाइल संशोधन समय, ठीक से सहानुभूति और इतने पर प्रतियां) और यदि आप किसी निर्देशिका को कॉपी करने की कोशिश कर रहे हैं, तो यह पूछता है कि क्या इसे कॉपी करना चाहिए (पुनरावर्ती)।

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