स्क्रिप्ट की निर्देशिका के लिए वर्तमान कार्य निर्देशिका कैसे सेट करें?


569

मैं बैश स्क्रिप्ट लिख रहा हूं। मुझे वर्तमान कार्यशील निर्देशिका की हमेशा वह निर्देशिका चाहिए जो स्क्रिप्ट में स्थित है।

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


क्या आपने कहीं (हार्डकोड) उचित निर्देशिका में cd / usr / bin को cd स्क्रिप्ट डालने पर विचार किया है और फिर अपनी स्क्रिप्ट निष्पादित करें?
डग नबबिट

2
आपको स्क्रिप्ट की निर्देशिका की आवश्यकता क्यों है? अंतर्निहित समस्या को हल करने के लिए शायद एक बेहतर तरीका है।
3:00 पर bstpierre

12
मैं केवल यह बताना चाहता हूं कि आप जिस व्यवहार को "स्पष्ट रूप से अवांछनीय" कहते हैं, वह वास्तव में पूरी तरह से आवश्यक है - अगर मैं चलाता myscript path/to/fileहूं तो मुझे उम्मीद है कि स्क्रिप्ट मेरी वर्तमान निर्देशिका के सापेक्ष पथ / / से / फ़ाइल का मूल्यांकन करने के लिए है, स्क्रिप्ट जो भी हो, निर्देशिका नहीं होती है। में स्थित होना। इसके अलावा, ssh remotehost bash < ./myscriptबीएएस एफएक्यू उल्लेख के साथ एक स्क्रिप्ट चलाने के लिए आप क्या करेंगे ?
गॉर्डन डेविसन


3
cd "${BASH_SOURCE%/*}" || exit
कांव-कांव

जवाबों:


655
#!/bin/bash
cd "$(dirname "$0")"

7
dirname रिटर्न '।' विंडोज के तहत बैश का उपयोग करते समय। इसलिए, पॉल का जवाब बेहतर है।
तवरोह

7
साथ ही लौटा देता है। ' मैक OSX में
बेन क्लेटन

4
यह ध्यान देने योग्य है कि अगर कोई प्रतीकात्मक कड़ी का हिस्सा बन जाए तो चीजें टूट सकती हैं $0। अपनी स्क्रिप्ट में, आप उदाहरण के लिए, ../../स्क्रिप्ट के स्थान से दो स्तरों की निर्देशिका को संदर्भित करने के लिए उम्मीद कर सकते हैं , लेकिन यह जरूरी नहीं कि प्रतीकात्मक लिंक खेलने में हों।
ब्रायन गॉर्डन

20
यदि आपने स्क्रिप्ट को इस रूप में कहा है ./script, .तो सही निर्देशिका है, और .इसे बदलने से यह उसी निर्देशिका में समाप्त हो जाएगा जहां scriptस्थित है, अर्थात वर्तमान कार्यशील निर्देशिका में।
ndim

6
यदि आप वर्तमान निर्देशिका से स्क्रिप्ट को चलाते हैं bash script.sh, तो मान $0है script.sh। आपके लिए cdकमांड "काम" करने का एकमात्र तरीका है क्योंकि आप विफल कमांड के बारे में परवाह नहीं करते हैं। यदि आप यह सुनिश्चित करने के लिए उपयोग कर रहे थे कि set -o errexit(aka:) set -eयह सुनिश्चित करने के लिए कि आपकी स्क्रिप्ट पिछले विफल आदेशों को नहीं उड़ाती है, तो यह काम नहीं करेगा क्योंकि cd script.shएक त्रुटि है। विश्वसनीय [बैश विशिष्ट] तरीका हैcd "$(dirname ${BASH_SOURCE[0]})"
ब्रूनो ब्रोंस्की

322

निम्नलिखित भी काम करता है:

cd "${0%/*}"

इस StackOverflow उत्तर में सिंटैक्स का अच्छी तरह से वर्णन किया गया है ।


17
स्पष्टीकरण यह कैसे काम करता है: stackoverflow.com/questions/6393551/…
kenorb

25
अगर रास्ते में व्हॉट्सएप हो तो उद्धरण चिह्नों में संलग्न करना न भूलें। यानी सीडी "$ {0% / *}"
एच। राबी

17
यह विफल हो जाता है अगर स्क्रिप्ट के साथ कॉल किया जाता है bash script.sh- $0बस फ़ाइल का नाम होगा
क्रिस वाट

17
मैं कहूंगा कि यह उत्तर बहुत ही संक्षिप्त है। सिंटैक्स के बारे में आपने शायद ही कुछ सीखा हो। इसे कैसे पढ़ा जाए, इसके बारे में कुछ विवरण उपयोगी होगा।
फ्रैक्चर

2
यह ट्रिक एक सबस्क्रिप्शन को भी नहीं बढ़ाता है इसलिए स्पीड फ्रीक के लिए अच्छा है।
टेकनोपॉल

184

निम्नलिखित सरल वन-लाइनर्स आज़माएं:


सभी UNIX / OSX / Linux के लिए

dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)

दे घुमा के

dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)

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

नोट: बैश में, के ${BASH_SOURCE[0]}पक्ष में उपयोग करें $0, अन्यथा इसे सोर्स करते समय रास्ता टूट सकता है ( source/ .)।


लिनक्स, मैक और अन्य के लिए * बीएसडी:

cd "$(dirname "$(realpath "$0")")";

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

नोट: यदि आप बैश का उपयोग कर रहे हैं, तो ${BASH_SOURCE[0]}इसके पक्ष में उपयोग करें $0, अन्यथा सोर्सिंग ( source/ .) के दौरान रास्ता टूट सकता है ।

अन्यथा आप ऐसा कुछ आज़मा सकते हैं (यह पहले मौजूदा उपकरण का उपयोग करेगा):

cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"

लिनक्स के लिए विशिष्ट:

cd "$(dirname "$(readlink -f "$0")")"

* BSD / Mac पर GNU रीडलिंक का उपयोग:

cd "$(dirname "$(greadlink -f "$0")")"

नोट: आपको coreutilsस्थापित करना होगा (उदाहरण के लिए 1. होमब्रे , 2. स्थापित करें brew install coreutils)।


मारपीट में

बैश में, आप इसे प्राप्त करने के लिए पैरामीटर विस्तार का उपयोग कर सकते हैं , जैसे:

cd "${0%/*}"

लेकिन यह काम नहीं करता है यदि स्क्रिप्ट उसी निर्देशिका से चलाई जाती है।

वैकल्पिक रूप से आप निम्नलिखित फ़ंक्शन को bash में परिभाषित कर सकते हैं:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

यह फ़ंक्शन 1 तर्क लेता है। यदि तर्क में पहले से ही पूर्ण पथ है, तो इसे प्रिंट करें जैसा कि यह है, अन्यथा $PWDचर + फ़ाइल नाम तर्क ( ./उपसर्ग के बिना ) प्रिंट करें ।

या यहाँ डेबियन .bashrcफ़ाइल से लिया गया संस्करण है :

function realpath()
{
    f=$@
    if [ -d "$f" ]; then
        base=""
        dir="$f"
    else
        base="/$(basename "$f")"
        dir=$(dirname "$f")
    fi
    dir=$(cd "$dir" && /bin/pwd)
    echo "$dir$base"
}

सम्बंधित:

यह सभी देखें:

मैं एक मैक पर जीएनयू के रीडलिंक का व्यवहार कैसे प्राप्त कर सकता हूं?


4
लोकप्रिय लोगों की तुलना में बहुत बेहतर उत्तर क्योंकि यह सिसलींक का समाधान करता है, और विभिन्न ओएस के लिए खाता है। धन्यवाद!
डेनिस

इस उत्तर के लिए धन्यवाद। शीर्ष एक ने मेरे मैक पर काम किया ... लेकिन cpकमांड में @ स्विच क्या करता है ?
टॉबी

3
एक डबल डैश ( --) कमांड विकल्पों के अंत को दर्शाने के लिए कमांड में उपयोग किया जाता है, इसलिए डैश या अन्य विशेष वर्ण वाली फाइलें कमांड को नहीं तोड़ेंगी। उदाहरण के माध्यम से फ़ाइल बनाने की कोशिश करें touch "-test"और touch -- -test, फिर फ़ाइल को इसके माध्यम से निकालें rm "-test"और rm -- -testअंतर देखें।
केनोरब

1
अगर मैं कर सकता / सकती हूं तो मैं अपना अपवोट
Realpath को

1
@ एलश यह कहता है कि केवल डेबियन realpathपैकेज को पदावनत किया जाता है, जीएनयू को नहीं realpath। यदि आपको लगता है कि यह स्पष्ट नहीं है, तो आप एक संपादन का सुझाव दे सकते हैं।
kenorb

73
cd "$(dirname "${BASH_SOURCE[0]}")"

यह आसान है। यह काम करता हैं।


1
यह स्वीकृत उत्तर होना चाहिए। OSX और Linux Ubuntu पर काम करता है।
डेविड रिसाटो क्रूज़

5
यह बहुत अच्छा काम करता है जब स्क्रिप्ट बी को अन्य स्क्रिप्ट ए से अलग किया जाता है और आपको स्क्रिप्ट बी के सापेक्ष पथ का उपयोग करने की आवश्यकता है। धन्यवाद।
एनरिको

5
यह भी उन लोगों के लिए Cygwin में काम करता है जो दुर्भाग्य से विंडोज को छूने के लिए पर्याप्त हैं।
ब्रूनो ब्रॉन्स्की

3
याcd "${BASH_SOURCE%/*}" || exit
जूल

MacOS Mojave पर काम करता है
जुआन बोरो

6

स्वीकृत उत्तर उन लिपियों के लिए अच्छी तरह से काम करता है, जिन्हें अन्यत्र समरूप नहीं किया गया है, जैसे कि $PATH

#!/bin/bash
cd "$(dirname "$0")"

हालाँकि यदि स्क्रिप्ट को सिमलिंक से चलाया जाता है,

ln -sv ~/project/script.sh ~/bin/; 
~/bin/script.sh

यह ~/bin/निर्देशिका में सीडी करेगा और निर्देशिका नहीं ~/project/, जो संभवतः आपकी स्क्रिप्ट को तोड़ देगा यदि उद्देश्य के cdसापेक्ष निर्भरता को शामिल करना है~/project/

सिमलिंक सुरक्षित उत्तर नीचे है:

#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

readlink -f संभावित सिम्लिंकड फ़ाइल के पूर्ण पथ को हल करने के लिए आवश्यक है।

फ़ाइलपैथ का समर्थन करने के लिए उद्धरण आवश्यक हैं, जिसमें संभवतः व्हाट्सएप (बुरा अभ्यास) हो सकता है, लेकिन यह मानने के लिए सुरक्षित नहीं है कि यह मामला नहीं होगा)


4

यह स्क्रिप्ट मेरे लिए काम करती है:

#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

Pwd कमांड लाइन स्क्रिप्ट की लोकेशन को वर्तमान वर्किंग डाइरेक्टरी के रूप में ग्रहण करती है, इससे कोई फर्क नहीं पड़ता कि मैं इसे कहां से चलाता हूं।


3
realpathहर जगह स्थापित होने की संभावना नहीं है। जो ओपी की स्थिति पर निर्भर करता है, कोई फर्क नहीं पड़ता।
bstpierre

मेरा सिस्टम नहीं है, realpathलेकिन यह है readlinkजो समान होने लगता है।
अगली सूचना तक रोक दिया गया।

2
कौन-सी डिस्टर्ब में वास्तविक रूप से डिफ़ॉल्ट रूप से स्थापित नहीं है? उबंटू के पास है।
kenorb


1
cd "`dirname $(readlink -f ${0})`"

क्या आप कृपया अपना उत्तर बता सकते हैं?
ज़ुलु

1
हालाँकि यह कोड समस्या को हल करने में मदद कर सकता है, लेकिन यह इस बात की व्याख्या नहीं करता कि क्यों और / या यह कैसे उत्तर देता है। इस अतिरिक्त संदर्भ को प्रदान करने से इसके दीर्घकालिक शैक्षिक मूल्य में काफी सुधार होगा। कृपया स्पष्टीकरण जोड़ने के लिए अपने जवाब को संपादित करें, जिसमें सीमाएं और मान्यताएं शामिल हैं।
टॉबी स्पाइट

-5
echo $PWD

पीडब्ल्यूडी एक पर्यावरण चर है।


5
यह केवल निर्देशिका से बुलाया जाता है, निर्देशिका नहीं जहां स्क्रिप्ट है।
8

-6

यदि आपको केवल वर्तमान कार्य निर्देशिका को प्रिंट करने की आवश्यकता है तो आप इसका अनुसरण कर सकते हैं।

$ vim test

#!/bin/bash
pwd
:wq to save the test file.

निष्पादन की अनुमति दें:

chmod u+x test

फिर स्क्रिप्ट निष्पादित करें ./testतब तक आप वर्तमान कार्य निर्देशिका देख सकते हैं।


2
सवाल अपने में स्क्रिप्ट रन सुनिश्चित करने के लिए कैसे था खुद निर्देशिका, अगर वह यह है कि सहित नहीं कार्यशील निर्देशिका। तो यह कोई जवाब नहीं है। वैसे भी, यह सिर्फ ... के बजाय क्यों चल रहा है pwd? मेरे लिए बहुत सारे बर्बाद किए गए कुंजीपट की तरह लगता है।
अंडरस्कोर_ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.