2008-10-27 11 views
10

क्या आपको लगता है कि बैश या पर्ल स्क्रिप्ट के अंदर निर्देशिका बदलना स्वीकार्य है? या किसी को हर कीमत पर ऐसा करने से बचना चाहिए?स्क्रिप्ट के अंदर काम करने वाली निर्देशिकाओं को बदलने के लिए सबसे अच्छा अभ्यास क्या है?

इस मुद्दे के लिए सबसे अच्छा अभ्यास क्या है?

+0

मुझे प्रश्न नहीं मिला। कोई भी कैसे बता सकता है कि आपकी स्क्रिप्ट ने एक नई निर्देशिका में सीडी किया है? –

+0

वर्तमान उत्तर इस "यह वैध वाक्यविन्यास से संपर्क करते हैं और वह माता-पिता के खोल को प्रभावित नहीं करते हैं, इसलिए यह ठीक है" परिप्रेक्ष्य। मैं इस प्रश्न के लिए एक और हिस्सा देखता हूं, जैसे "स्क्रिप्ट्स में cd'ing है बदसूरत कोडिंग शैली, पाइथन या खराब चुने हुए चर नामों की लंबी लाइनों के समान - कुछ ऐसा किया जा सकता है लेकिन इससे बचने का सबसे अच्छा अभ्यास है"। – dfarrell07

उत्तर

15

वर्तमान कार्यशील निर्देशिका निष्पादन खोल के लिए स्थानीय है, इसलिए आप उपयोगकर्ता को तब तक प्रभावित नहीं कर सकते जब तक कि वह "डॉटिंग" नहीं कर रहा है (इसे वर्तमान खोल में चला रहा है, इसे सामान्य रूप से एक नई खोल प्रक्रिया बनाने के विपरीत) स्क्रिप्ट।

ऐसा करने का एक बहुत अच्छा तरीका subshells है, जो मैं अक्सर उपनाम में क्या उपयोग करने के लिए है।

alias build-product1='(cd $working-copy/delivery; mvn package;)' 

paranthesis सुनिश्चित करें कि आदेश एक उप खोल से क्रियान्वित किया जाता है कर देगा, और इस तरह मेरी खोल के कार्यशील निर्देशिका को प्रभावित नहीं करेगा। इसके अलावा यह अंतिम कार्य-निर्देशिका को प्रभावित नहीं करेगा, इसलिए सीडी -; अपेक्षित के रूप में काम करता है।

4

मैं इस बार ऐसा नहीं करते हैं, लेकिन कभी कभी यह काफी सिर दर्द का एक सा बचा सकता है। बस सुनिश्चित करें कि यदि आप निर्देशिका बदलते हैं, तो आप हमेशा उस निर्देशिका में बदल जाते हैं, जिसे आपने शुरू किया था। अन्यथा, कोड पथ बदलना कहीं भी एप्लिकेशन को छोड़ सकता है, यह नहीं होना चाहिए।

+0

यूनिक्स डेरिवेटिव्स पर नहीं, यह नहीं हो सका। –

+0

हां यह अगर आप "एप्लिकेशन" को "एक ही निष्पादन योग्य, लेकिन अलग-अलग कार्यों" के रूप में ले सकते हैं - तो आप केवल मूल प्रक्रिया 'cwd को नहीं बदल सकते हैं। – Tanktalus

+0

"एप्लिकेशन" शब्द की किस तरह की व्याख्या आपको यह सोचने के लिए प्रेरित करेगी ?? – ephemient

1

भी विचार करें कि यूनिक्स और विंडोज एक निर्देशिका ढेर में निर्माण किया है: pushd and popd। इसका उपयोग करना बेहद आसान है।

25

तरह ह्यूगो ने कहा, वहाँ कोई समस्या नहीं है, तो आप अपने माता पिता प्रक्रिया के CWD को प्रभावित नहीं कर सकते हैं।

कहाँ सवाल लागू है आप पूरी प्रक्रिया को नियंत्रित नहीं करते हैं, एक सबरूटीन या मॉड्यूल में की तरह है। उन मामलों में आप उसी निर्देशिका में subroutine से बाहर निकलना चाहते हैं जैसे आपने दर्ज किया है, अन्यथा क्रिया-पर-दूरी दूरी को सूक्ष्मताएं जिसमें बग का कारण बनता है।

हाथ से

यह करने के लिए आप कर सकते हैं ...

use Cwd; 
sub foo { 
    my $orig_cwd = cwd; 
    chdir "some/dir"; 

    ...do some work... 

    chdir $orig_cwd; 
} 

लेकिन यह है कि समस्या है। अगर सबराउटिन जल्दी लौटाता है या मर जाता है (और अपवाद फंस जाता है) तो आपका कोड अभी भी some/dir में होगा। इसके अलावा, chdir एस विफल हो सकता है और आपको प्रत्येक उपयोग की जांच करना याद रखना होगा। Bleh।

सौभाग्य से, इस आसान बनाने के लिए एक जोड़े मॉड्यूल है। फ़ाइल :: pushd एक है, लेकिन मैं File::chdir पसंद करता हूं।

use File::chdir; 
sub foo { 
    local $CWD = 'some/dir'; 

    ...do some work... 
} 

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

+0

मैं इसे लेता हूं फ़ाइल :: chdir कोर मॉड्यूल नहीं है? यदि आप कोर मॉड्यूल से चिपकने की कोशिश कर रहे हैं, तो हूगो की विधि अगले सबसे अच्छे विकल्प है? – SSilk

+0

@SSilk ह्यूगो की तकनीक अलग-अलग है और अन्य आदेशों को चलाने वाली स्क्रिप्ट बनाने जैसी चीजों पर अधिक लागू होती है। मेरा कार्यक्रम और पुस्तकालयों के आंतरिक पर लागू होता है। दोनों बदलते निर्देशिका को किसी और चीज को प्रभावित करने से पूरी तरह अलग करने की कोशिश करते हैं। – Schwern

2

पर्ल के लिए, आपके पास सीपीएएन से File::pushd मॉड्यूल है जो स्थानीय रूप से कार्यशील निर्देशिका को काफी सुरुचिपूर्ण बनाता है। सारांशों का उद्धरण:

use File::pushd; 

    chdir $ENV{HOME}; 

    # change directory again for a limited scope 
    { 
     my $dir = pushd('/tmp'); 
     # working directory changed to /tmp 
    } 
    # working directory has reverted to $ENV{HOME} 

    # tempd() is equivalent to pushd(File::Temp::tempdir) 
    { 
     my $dir = tempd(); 
    } 

    # object stringifies naturally as an absolute path 
    { 
    my $dir = pushd('/tmp'); 
    my $filename = File::Spec->catfile($dir, "somefile.txt"); 
    # gives /tmp/somefile.txt 
    } 
3

मैं ऊपर श्वार्न और ह्यूगो की दूसरी टिप्पणियां दूंगा। नोट अनपेक्षित निकास की स्थिति में मूल निर्देशिका में लौटने के बारे में श्वेर्न की सावधानी बरतें। उन्होंने इसे संभालने के लिए उचित पर्ल कोड प्रदान किया। मैं खोल (बैश, कॉर्न, बोर्न) जाल कमांड को इंगित करूंगा।

जाल "सीडी $ saved_dir" 0

subshell बाहर निकलने पर saved_dir वापस आ जाएगी (आप फ़ाइल .'ing रहे हैं)।

माइक

0

यह बिल्कुल कोशिश करते हैं और पूरी तरह से मात्रा निर्धारित रास्तों का उपयोग, और किसी भी मान्यताओं जो निर्देशिका पर आप अभी हैं नहीं करने के लिए संभव है? जैसे

use FileHandle; 
use FindBin qw($Bin); 
# ... 
my $file = new FileHandle("< $Bin/somefile"); 

बजाय

use FileHandle; 
# ... 
my $file = new FileHandle("< somefile"); 

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

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

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