2009-12-31 10 views
5

एक अस्थायी चर का उपयोग किए बिना जल्दी से यह करने के लिए किसी भी तरह से? क्या फ़ंक्शन में कोई अंतर्निहित है?यूनिक्स में फ़ाइल नामों को कैसे स्वैप करें?

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

  • फ़ाइल एक है नाम बी name.file

मैं फ़ाइल एक के लिए करना चाहते हैं ए-name.file और फ़ाइल नाम से फ़ाइल बी नाम ए-name.file है बी का नाम बी-नाम.फाइल होगा।

मैं मानता हूँ, स्थिति अक्सर होता है नहीं, लेकिन यह सिर्फ मुझे क्या हुआ और मैं एक त्वरित सुधार करना चाहता था।

+0

क्या आप फ़ाइल नामों को स्वैप करके क्या मतलब है? फ़ाइल "ए" को "बी" और v.v. के रूप में नामित करना? – Kimvais

+0

जस्ट स्वैपिंग फ़ाइल नामों के लिए कोई अंतर्निहित फ़ंक्शन नहीं है! जैसा कि आपने कहा था कि आप इसे एक शेल स्क्रिप्ट और एक अस्थायी चर द्वारा कर सकते हैं –

+1

क्या आपके पास एक विशिष्ट कार्यान्वयन भाषा है, या आपको एक (खोल) कमांड की आवश्यकता है? किस प्रकार का विभाजन इस्तेमाल किया जा रहा है? (क्या एनएफएस पर काम करने की आवश्यकता है?) अस्थायी चर के साथ क्या गलत है? –

उत्तर

4

ठीक है, बेवकूफ सवाल की तरह कुछ कर रही हो जाएंगे, लेकिन क्यों आप बस की तरह कुछ (एक खोल स्क्रिप्ट में) नहीं कर सकते:

mv $fileA $fileA.$$ 
mv $fileB $fileA 
mv $fileA.$$ $fileB 

और हाँ निश्चित रूप से यह एक का उपयोग करता है अस्थायी फ़ाइल, लेकिन इसके बाद अन्य उत्तरों संक्षिप्त है।

+4

यह एक अस्थायी फ़ाइल नाम का उपयोग करता है, लेकिन कम से कम कोई प्रतिलिपि नहीं चल रही है। –

3
खोल स्क्रिप्ट स्तर पर

- वहाँ एक मानक आदेश नहीं है और नाम बदलने में कम से कम एक अस्थायी फ़ाइल नाम शामिल है (अलग फाइल सिस्टम पर फाइल सावधान!)।

सी कोड स्तर पर, वहाँ एक मानक समारोह फ़ाइल नाम स्वैप करने के लिए सभी मशीनों पर उपलब्ध नहीं है - और कारकों में से एक अलग फाइल सिस्टम पर फ़ाइलों से निपटने का मुद्दा है।

एक एकल फाइल सिस्टम पर:

file1=one-file-name 
file2=tother-file 
file3=tmp.$$ 

trap "" 1 2 3 13 15 
ln $file1 $file3 
rm $file1 
ln $file2 $file1 
rm $file2 
ln $file3 $file2 
rm $file3 
trap 1 2 3 13 15 

यही कारण है नहीं पूरी तरह से मूर्ख प्रूफ - लेकिन यह एक अर्द्ध सभ्य सन्निकटन है अगर $ file1 और $ करें 2 एक ही फाइल सिस्टम पर कर रहे हैं (और मैं ' मान लिया है कि $ file3 एक ही फाइल सिस्टम पर एक नाम है)। सभी मौसाओं से निपटने के लिए इसे ठीक करना ... गैर-तुच्छ है। (। $ File1 == $ करें 2, उदाहरण के लिए विचार करें)

कोड simulates काफी प्रणाली कॉल है कि एक सी कार्यक्रम बनाने के लिए होता है - lnlink() और rm को मैप करने के unlink() को मैप करने के। नए (के रूप में, केवल बीस वर्ष की उम्र) समारोह rename() शायद अच्छे प्रभाव के लिए इस्तेमाल किया जा सकता - बशर्ते आप यह काम नहीं चलेगा क्या समझते हैं। लिंक और निकालने के बजाय mv कमांड का उपयोग करना मतलब है कि यदि आवश्यक हो तो फ़ाइलों को फ़ाइल सिस्टम के बीच स्थानांतरित किया जाएगा; यह सहायक हो सकता है - या इसका मतलब यह हो सकता है कि जब आप इसका इरादा नहीं रखते थे तो आपकी डिस्क स्थान भर जाती है। किसी त्रुटि भाग से पुनर्प्राप्त करना पूरी तरह से छोटा नहीं है, या तो।

1

शायद यह के साथ किया जा सकता है:

file_B = fopen(path_b, 'r'); 
rename(path_a, path_b); 

file_B_renamed = fopen(path_a, 'w'); 
/* Copy contents of file_B into file_B_renamed */ 
fclose(file_B_renamed); 
fclose(file_B); 

वहाँ एक तरह से (मैं POSIX कल्पना को देखने के लिए के माध्यम से खोज कर रहा हूँ, लेकिन मैं इस पर यकीन नहीं होता) से एक hardlink बनाने के लिए किया जा सकता है इनोड संख्या; जो

file_B = fopen(path_b, 'r'); 
rename(path_a, path_b); 
make_hardlink(file_B, path_a); 
+0

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

+0

क्योंकि वह एक अस्थायी फ़ाइल नाम नहीं चाहता है। यह एक मूर्खतापूर्ण बाधा है, लेकिन यह सवाल का हिस्सा है। – Tordek

+1

यह सच है। मेरा "मनमाना डेटा क्यों चलाएं" सवाल ज्यादातर उदारवादी था; हालांकि, यह वास्तव में मूर्खतापूर्ण बाधा के भीतर एक समाधान है, ऐसा लगता है कि प्रदर्शन के मुद्दों को दूर करने की संभावना है, इसलिए हमें शायद इन प्रभावों का वर्णन करना चाहिए और संबंधित हितधारकों को सुझाव देना चाहिए कि बाधा पर पुनर्विचार किया जाए। :) – fennec

1

"स्वैप फ़ाइल नाम" का क्या अर्थ है? क्या आप फाइल सिस्टम, या सिर्फ अपने प्रोग्राम में चर के बारे में बात कर रहे हैं?

यदि आपका प्रोग्राम सी ++ है, और आपके पास तारों में दो फ़ाइल नाम हैं, और उन्हें स्वैप करना चाहते हैं, तो std :: swap का उपयोग करें।

std::string filenameA("somefilename"); 
std::string filenameB("othername"); 

std::swap(filenameA, filenameB); 
std::cout << filenameA << std::endl; // prints "othername" 

आप डिस्क पर दो फ़ाइलों है, और आप के नाम एक दूसरे के साथ सामग्री स्वैप करने के लिए चाहते हैं, तो नहीं, कोई रास्ता नहीं करने के लिए आसानी से कि करने के लिए, यदि आप: यह केवल प्रोग्राम में चर में परिवर्तन हार्ड लिंक को संरक्षित करना चाहते हैं। यदि आप सिर्फ "सुरक्षित बचत" करना चाहते हैं, तो यूनिक्स नाम बदलें() सिस्टम कॉल गंतव्य फ़ाइल को एक परमाणु संचालन में स्रोत फ़ाइल के साथ क्लॉबर करेगा (जैसा परमाणु के रूप में अंतर्निहित फाइल सिस्टम द्वारा समर्थित किया जा सकता है)।

std::string savename(filename); 
savename += ".tmp"; 
... write data to savename ... 
if (::rename(savename.c_str(), filename.c_str()) < 0) { 
    throw std::exception("oops!"); 
} 

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

::link(oldfile, tempfile); 
::rename(newfile, oldfile); 
::rename(tempfile, newfile); 

आप लिंक के बाद दुर्घटना, तो आप में नए डेटा उपलब्ध हो जाए:

oldfile संभालने "filname.dat" और newfile कि "filename.dat.bak" क्या आप इस मिलेगा newfile, और oldfile और tempfile में पुराना डेटा। आप पहली बार नाम बदलने के बाद दुर्घटना, तो आप tempfile में oldfile में नया डेटा, और पुराने डेटा उपलब्ध हो (लेकिन newfile नहीं!)

8

डार्विन/मैक ओएस एक्स exchangedata() सिस्टम कॉल है:

exchangedata() फ़ंक्शन एक परमाणु फैशन में पथ 1 और पथ 2 द्वारा संदर्भित फ़ाइलों की सामग्री को स्वैप करता है। यही है, सभी समवर्ती प्रक्रियाएं या तो पूर्व-विनिमय राज्य या बाद के आदान-प्रदान वाले राज्य को देखेंगे; वे एक असंगत स्थिति में फ़ाइलों को कभी नहीं देख सकते हैं।

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

5

यह थोड़ा सहायक के साथ किया जा सकता है, बस .bashrc, .zshrc या जहां आपकी कॉन्फ़िगरेशन डालें।

function swap() { mv $1 $1._tmp && mv $2 $1 && mv $1._tmp $2 } 

और नियमित रूप से समारोह के रूप में इसका इस्तेमाल करते हैं:

$ cat a b 
Alfa 
Beta 

$ swap a b && cat a b 
Beta 
Alfa 
+0

यह समाधान प्रश्न के सबसे आसान और निकटतम है। –

संबंधित मुद्दे