एक फ़ोल्डर में कुछ फ़ाइलों को स्थानांतरित करने से पूरे फ़ोल्डर को स्थानांतरित करने में अधिक समय क्यों लगता है?


21

मेरे ubuntu क्लाउड सर्वर पर लाखों चित्र हैं। जब मैं mvकमांड का उपयोग करके 12 मिलियन छवियों वाला एक पूर्ण फ़ोल्डर ले जाता हूं , तो यह लगभग तुरंत होता है। हालाँकि, जब मैं mvकेवल छवियाँ (फ़ोल्डर नहीं) तो कुछ समय लगता है। क्या सभी छवियों को फ़ोल्डर्स के रूप में जल्दी से स्थानांतरित करने का एक तरीका है?

यह क्या हो रहा है:

  1. src फ़ोल्डर में 12 मिलियन छवियां हैं और मैं इसे dst फ़ोल्डर का उपयोग करके स्थानांतरित करता हूं

    $ mv  src ../dst
    

    तुरंत होता है

  2. अंदर src फ़ोल्डर मैं यह करने के लिए कदम:

    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
    

    इसमें कुछ समय लगता है।

क्या दूसरी प्रक्रिया को गति देने का एक तरीका है?


1
समाधान नहीं - लेकिन स्पष्ट करने के लिए: cmd2 को धीमा होना चाहिए और cmd1 क्योंकि यह खोज का उपयोग कर रहा है और फिर परिणाम के लिए कदम को निष्पादित करता है। यह पूर्व-खोज-प्रक्रिया के बिना एक सीधी चाल के रूप में तेज़ नहीं हो सकता है।
dufte

शायद dstएक विभाजन में है जबकि ../../dstदूसरे पर है।
फुलेव

जैसा कि लिखा गया है यह मान्य खोज आमंत्रण की तरह भी नहीं दिखता है। यह किसी भी {}तर्क की कमी है कि फ़ाइल नाम का विस्तार किया जाएगा।
आर ..

मैंने एक संपादन प्रस्तुत किया है जो शीर्षक को बदल देता है, "छवियों" के संदर्भ को हटाता है और इसे मामले के नग के साथ बदल देता है - यह व्यक्तिगत फ़ाइलों को स्थानांतरित कर रहा है बनाम पूरे फ़ोल्डर को स्थानांतरित कर रहा है। मुझे आशा है कि इसे किसी व्यक्ति द्वारा इसे करने के लिए इसे स्वीकार कर लिया जाएगा।
मोंटी हार्डर

1
यह एक वैध आह्वान नहीं है find। प्रति फ़ाइल एक बार find ... -exec mv -t ../../dst/ {} \;कॉल करेगा mv; find ... -exec mv -t ../../dest {} +बहुत तेजी से हो सकता है, प्रति कॉल जितनी संभव हो उतने फ़ाइलों की प्रतिलिपि बना रहा है, लेकिन अभी भी उतना तेज़ नहीं है जितना कि निर्देशिका को स्थानांतरित करने के रूप में dadexix86 द्वारा समझाया गया है
चेपनर

जवाबों:


50

टीएल; डीआर : नहीं

फ़ाइलों की एक छोटी राशि के लिए, आपको जरूरत नहीं होगी find, लेकिन इस सरलीकृत और छोटे मामले में, यदि आप बस

mv *.jpg ../../dst/

एक बार में पूरी निर्देशिका को स्थानांतरित करने की तुलना में अधिक समय लगेगा।


क्यूं कर? बात समझने की है कि क्या mvकरता है।

संक्षेप में, mvएक इनोड से एक नंबर (जो एक निर्देशिका या एक फ़ाइल की पहचान करता है) को स्थानांतरित करता है (एक निर्देशिका जिसमें यह है) दूसरे से, और ये सूचकांक फ़ाइल सिस्टम या FAT (यदि फ़ाइल सिस्टम की पत्रिका में अपडेट किए जाते हैं) इस तरह से लागू किया जाता है)।

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

इसलिए, जब आप mv एक निर्देशिका, आप एक बार इस ऑपरेशन कर रहे हैं ।

लेकिन जब आप 1 मिलियन फ़ाइलों को स्थानांतरित करते हैं, तो आप इस ऑपरेशन को 1 मिलियन बार कर रहे हैं ।

आपको एक व्यावहारिक उदाहरण देने के लिए, आपके पास कई शाखाओं वाला एक पेड़ है। विशेष रूप से, एक नोड है जिसमें 1 मिलियन शाखाएं जुड़ी हुई हैं।
इन शाखाओं को काटने के लिए और उन्हें कहीं और स्थानांतरित करने के लिए, आप या तो उनमें से प्रत्येक को काट सकते हैं, इसलिए आप 1 मिलियन कटौती करते हैं, या आप नोड से ठीक पहले काटते हैं, इस प्रकार सिर्फ एक कट बनाते हैं (यह फ़ाइलों को स्थानांतरित करने के बीच का अंतर है और निर्देशिका)।


4
आपको यह शामिल करना चाहिए कि एक mvही फाइल सिस्टम पर केवल TOC प्रविष्टि को फिर से लिखना है।
वीडियोनौथ

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

10
उम। mv *.jpg12 मिलियन फ़ाइलों के लिए असफल होने की संभावना है, यही कारण है कि वह खोज का उपयोग करता है। अधिकांश यूनिक्स, लिनक्स शामिल थे मुझे विश्वास है (जब तक कि किसी ने इसे पिछले 5-10 वर्षों में नहीं बदला है) कमांड लाइन की सीमित अधिकतम लंबाई है। मुझे लगता है कि यह लिनक्स के लिए लंबे समय तक 64K था। एक ही सीमा पर्यावरण चर पर लागू होती है, मुझे पूरा यकीन है।
ज़ैन लिंक्स

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

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

13

यह अभी भी धीमा होगा, क्योंकि जैसा कि उल्लेख किया गया है, फ़ाइल सिस्टम को प्रत्येक फ़ाइल नाम को उसके नए स्थान पर स्थानांतरित करना होगा।

हालाँकि, आपके पास अभी जो है उससे आप इसे गति दे सकते हैं।

आपकी खोज कमांड प्रत्येक फ़ाइल के लिए एक बार निष्पादन चलाता है। इसलिए यह mv12 मिलियन फाइलों के लिए 12 मिलियन बार कमांड लॉन्च करता है । इसमें दो तरह से सुधार किया जा सकता है।

  • अंत में एक प्लस जोड़ें:
    find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
    यह सुनिश्चित करने के लिए कि यह आपके संस्करण में समर्थित है, मैन-पेज की जाँच करें find। इसका प्रभाव mvकमांड की एक श्रृंखला को चलाने के लिए होना चाहिए, जितने फ़ाइलनाम के साथ प्रत्येक कमांड-लाइन पर फिट होंगे।

  • उपयोग findऔर xargsएक साथ। NUL का उपयोग करेगा, शून्य बाइट्स उर्फ फ़ाइल नाम को अलग करने के। यह प्लस किसी भी समस्या को ठीक करता है अन्यथा फ़ाइल नामों में रिक्त स्थान के साथ होगा। आदेश से फ़ाइल नामों की सूची पढ़ा जाएगा कमान और चलाने फिट होगा के रूप में कई फ़ाइल नाम के रूप में पर आदेश।
    find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
    -print0xargs -0xargsxargsfindmv


7

आपका भ्रम फ़ाइल सिस्टम एब्स्ट्रैक्शन से आता है जो आपको विश्वास दिलाता है कि एक फ़ोल्डर में फाइल और अन्य फ़ोल्डर एक ट्री-जैसे फैशन में हैं। यह वास्तव में सच नहीं है: एक फाइल सिस्टम के भीतर सभी फाइलें और निर्देशिका एक ही स्तर पर स्थित हैं और कुछ प्रकार की संख्याओं के साथ पहचानी जाती हैं, जो कार्यान्वयन पर निर्भर हैं। निर्देशिकाएँ केवल विशेष फाइलें हैं जिनमें अन्य फ़ाइलों की सूची है।

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

mv src ../dstनिर्देशिका से एक सूची प्रविष्टि चाल .निर्देशिका के लिए ../dst, तो यह तेज है।

find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/लाखों प्रविष्टियों को स्थानांतरित करना है, इसलिए यह धीमी है। यह संभावित रूप से तेज हो सकता है यदि आप mvकेवल एक बार और प्रति फ़ाइल एक बार कॉल करते हैं, और mvकमांड स्वयं एक ही चरण में कई निर्देशिका प्रविष्टियों को स्थानांतरित करने के लिए अनुकूलित हो सकती है, लेकिन जब तक आप एकल निर्देशिका को स्थानांतरित नहीं करते हैं, तब तक इसे बनाने का कोई तरीका नहीं है ।


4

एक सरलीकृत उत्तर

फ़ाइल को स्थानांतरित करना 3 चरण है:

  • जोड़ें () गंतव्य फ़ोल्डर की इनोड सूची में फ़ाइल के लिए एक लिंक
  • जांचें कि क्या लिंक सफलतापूर्वक जोड़ा गया था
  • निकालें () स्रोत फ़ोल्डर की सूची से लिंक अगर ऊपर की जाँच एक सफलता थी।

यह प्रक्रिया फ़ाइल या फ़ोल्डर के लिए समान है।
और स्पष्ट रूप से 1 फ़ाइल के लिए ऐसा करना 100 फ़ाइलों के लिए करने की तुलना में 100 तेज़ है।

man link जोड़ है ()
man unlinkहै हटाने ()
mvबस ऊपर उन दो आदेशों का उपयोग करता है और डेटा हानि को रोकने के लिए एक चेक-इन जोड़ता है।


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