2013-03-22 5 views
26

मुझे dir2 के अंदर dir1 (फ़ाइल या निर्देशिका) के प्रत्येक आइटम के लिए एक सिम्लिंक बनाने की आवश्यकता है। dir2 पहले से मौजूद है और एक सिम्लिंक नहीं है।`os.symlink` बनाम 'ln -s`

>>> os.symlink('/home/guest/dir1/*', '/home/guest/dir2/') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
OSError: [Errno 17] File exist 

मैं जानता हूँ कि मैं subprocess का उपयोग करें और ln आदेश चला सकते हैं: मैं कोई त्रुटि मिलती है

ln -s /home/guest/dir1/* /home/guest/dir2/

लेकिन अजगर में os.symlink का उपयोग कर: बैश में मैं आसानी से इस लक्ष्य को हासिल कर सकते हैं। मुझे वह समाधान नहीं चाहिए।

मुझे यह भी पता है कि os.walk या glob.glob का उपयोग कर कामकाज संभव है, लेकिन मैं जानना चाहता हूं कि os.symlink का उपयोग करके ऐसा करना संभव है या नहीं।

+3

मुझे लगता है कि * 'os.symlink' संबंधित सिस्टम कॉल की एक मात्र आवरण है (ठीक है, कम या ज्यादा) और इसलिए एक ही अर्थ विज्ञान आप एक पूर्ण से प्राप्त प्रदान नहीं करेगी * उस सिस्टम कॉल का उपयोग कर बढ़ी उपयोगिता। – 0xC0000022L

+1

"os.symlink'" आवश्यकता का उपयोग करके मैं इसे करना चाहता हूं? यदि सही काम करना 'ग्लोब' पर 'लूप' है, तो आप सही चीज़ क्यों नहीं करना चाहते हैं? – abarnert

+0

@abarnert मैं ऐसा करूँगा यदि मुझे करना है। मैं जानना चाहता था कि 'os.symlink' के साथ ऐसा करने का कोई तरीका है या नहीं। मैंने सोचा कि यह सब कुछ 'ln -s' प्रदान करेगा, लेकिन यह पता चला है कि यह नहीं करता है। – jurgenreza

उत्तर

45

os.symlink एक एकल सिम्लिंक बनाता है।

ln -s एकाधिक सिम्लिंक बनाता है (यदि इसका अंतिम तर्क निर्देशिका है, और एक से अधिक स्रोत हैं)।

dst = args[-1] 
for src in args[:-1]: 
    os.symlink(src, os.path.join(dst, os.path.dirname(src))) 

तो, यह कैसे काम करता है जब आप ln -s /home/guest/dir1/* /home/guest/dir2/ कार्य करें: अजगर बराबर कुछ की तरह है? आपका खोल वाइल्डकार्ड को कई तर्कों में बदलकर उस काम को बनाता है। यदि आप execln वाइल्डकार्ड के साथ कमांड के लिए थे, तो यह में * नामक एकल स्रोत को देखेगा, न कि उस निर्देशिका में सभी फाइलें।

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

dst = args[-1] 
for srcglob in args[:-1]: 
    for src in glob.glob(srcglob): 
     os.symlink(src, os.path.join(dst, os.path.dirname(src))) 

आप इसे os.symlink अकेले या इसके हिस्से के साथ नहीं कर सकते-क्योंकि ऐसा नहीं करता है। यह कहने जैसा है "मैं नाम पर फ़िल्टर किए बिना os.walk का उपयोग करके find . -name foo के बराबर करना चाहता हूं।" या, उस मामले के लिए, मैं अपने लिए खोल globbing के बिना ln -s /home/guest/dir1/* /home/guest/dir2/ के बराबर करना चाहता हूँ।"

सही जवाब glob, या fnmatch, या os.listdir प्लस एक regex, या जो भी आप पसंद करते हैं का उपयोग करने के

करो नहीं उपयोग os.walk, क्योंकि वह एक पुनरावर्ती फाइल सिस्टम की पैदल दूरी पर करता है।, तो यह है यहां तक ​​कि शैल के पास नहीं * विस्तार।

+0

+1 बहुत बहुत धन्यवाद – jurgenreza

12

* एक खोल विस्तार पैटर्न है, जो आपके मामले में "/home/guest/dir1/ से शुरू होने वाली सभी फाइलें" निर्दिष्ट करता है।

लेकिन यह आपके शैल की भूमिका है जो इस पैटर्न को से मेल खाने वाली फ़ाइलों के विस्तार के लिए है। ln कमांड नहीं है।

लेकिन os.symlink एक खोल नहीं है, यह एक ओएस कॉल है - इसलिए, यह शैल एक्सटेंशन पैटर्न का समर्थन नहीं करता है। आपको अपनी स्क्रिप्ट में वह काम करना होगा।

ऐसा करने के लिए, आप os.walk, या os.listdir का उपयोग कर सकते हैं। जैसा कि दूसरे उत्तर में इंगित किया गया है, उचित कॉल उस पर निर्भर करेगा जो आप करना चाहते हैं। (os.walk* के बराबर नहीं होगा)


खुद को समझाने के लिए: अपने टर्मिनल में एक यूनिक्स मशीन पर इस कमांड चलाएँ: python -c "import sys; print sys.argv" *। आप देखेंगे कि यह वह खोल है जो मिलान कर रहा है।

+0

+1। ध्यान रखें, हालांकि, विंडोज शैल (cmd.exe) थक गया है * इसे * लागू कार्यक्रम में पास करने से पहले ऐसा नहीं करता है। – 0xC0000022L

+0

+1 ठीक है ठीक है। :) – jurgenreza

+0

@ 0xC0000022L: ठीक है, निष्पक्ष होने के लिए, विंडोज 'ln' के साथ नहीं आता है। और एमएसवीसीआरटी (उनके libc) आपके 'मुख्य' शुरू होने से पहले 'argv' पर खोल ग्लोबिंग को अनुकरण करने के लिए एक हैक के साथ आता है, या जब आप इसे स्पष्ट रूप से पूछते हैं, और मुझे पूरा यकीन है कि यूनिक्स प्रोग्राम के अधिकांश बंदरगाह इसका उपयोग करेंगे या कुछ बराबर (उदाहरण के लिए, जो भी सिगविन करता है)। – abarnert

3

@abarnert यह खोल कि * पहचानता है और dir1 insside सभी वस्तुओं के साथ यह बदल देता है द्वारा सुझाव दिया गया है। इसलिए मैं का उपयोग कर लगता है कि os.listdir है सबसे अच्छा विकल्प:

for item in os.listdir('/home/guest/dir1'): 
    os.symlink('/home/guest/dir1/' + item, '/home/guest/dir2/' + item) 
+4

मैं '+' के बजाय 'os.path.join' का उपयोग करने का सुझाव देता हूं। –

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