बैश में एक फ़ाइल पथ तर्क में अंतिम dirname / फ़ाइल नाम प्राप्त करें


228

मैं SVN के लिए एक पोस्ट-कमिट हुक लिखने की कोशिश कर रहा हूं, जिसे हमारे विकास सर्वर पर होस्ट किया गया है। मेरा लक्ष्य उस निर्देशिका के लिए प्रतिबद्ध प्रोजेक्ट की एक प्रतिलिपि को स्वचालित रूप से जांचने का प्रयास करना है जहां यह सर्वर पर होस्ट किया गया है। हालाँकि, मुझे उसी स्ट्रिंग को केवल उसी निर्देशिका में चेकआउट करने के लिए स्क्रिप्ट को पास की गई डायरेक्टरी स्ट्रिंग में अंतिम निर्देशिका पढ़ने में सक्षम होना चाहिए जहाँ हमारी परियोजनाएँ होस्ट की गई हैं।

उदाहरण के लिए यदि मैं प्रोजेक्ट "उदाहरण" के लिए एक SVN प्रतिबद्ध करता हूं, तो मेरी स्क्रिप्ट को "/ usr / स्थानीय / svn / repos / उदाहरण" इसके पहले तर्क के रूप में मिलता है। मुझे स्ट्रिंग के अंत में सिर्फ "उदाहरण" प्राप्त करने की आवश्यकता है और फिर इसे एक और स्ट्रिंग के साथ संक्षिप्त करें ताकि मैं "/ सर्वर / रूट / उदाहरण" के लिए चेकआउट कर सकूं और परिवर्तनों को तुरंत लाइव देख सकूं।

जवाबों:


344

basename किसी पथ के निर्देशिका उपसर्ग को हटाता है:

$ basename /usr/local/svn/repos/example
example
$ echo "/server/root/$(basename /usr/local/svn/repos/example)"
/server/root/example

2
बेसन निश्चित रूप से मैं क्या देख रहा हूँ। हालांकि एक चर में संग्रहीत तर्क का आधार कैसे प्राप्त कर सकते हैं? जैसेSUBDIR="/path/to/whatever/$(basename $1)"
TJ L

5
@ tj111: लगता है कि नहीं है $1, या $1खाली है
sth

दुर्भाग्य से, यदि आप कमांड लपेटते हैं, तो बेसन एक अच्छा विचार नहीं है। बस कुछ ध्यान में रखना है
dtc

98

पथनाम के किसी भी मार्ग को प्राप्त करने के लिए निम्नलिखित दृष्टिकोण का उपयोग किया जा सकता है:

some_path=a/b/c
echo $(basename $some_path)
echo $(basename $(dirname $some_path))
echo $(basename $(dirname $(dirname $some_path)))

आउटपुट:

c
b
a

1
उन रास्तों के साथ काम नहीं करता जिनके पास स्थान हैं ... आप उद्धरण के साथ उस पर काबू पा सकते हैं ... जो किसी भी तरह से काम करता हैecho "$(basename "$(dirname "$pathname")")"
रे फॉस

75

बैश बाहरी कॉल करने के लिए बिना किसी पथ के अंतिम भाग प्राप्त कर सकते हैं basename:

subdir="/path/to/whatever/${1##*/}"

2
मेरे मैक पर, केसिंग संकेतन का उपयोग उस मामले के लिए dirname / basename से अधिक परिमाण के क्रम से अधिक है जहां आप कुछ हज़ार फ़ाइलों में से प्रत्येक के लिए कुछ तुच्छ काम कर रहे हैं।
जॉर्ज

1
d=/home/me/somefolder;subdir="/$d/${1##*/}"मैं कुछ के साथ समाप्त हो गया जैसे //home/me/somefolder//$ d वास्तव में एक पाश से आता है जैसा कि अपेक्षित है for d in $(find $SOMEFOLDER -maxdepth 1 -type d);का उपयोग subdir=$(basename $d)करता है।
बुटिक बटुक

1
@ButtleButkus: ( आउटपुट बेहतर है) या ग्लोबिंग का उपयोग whileकरने के बजाय इट्रेट के बजाय का उपयोग करना चाहिए : (अंतिम स्लैश काम करता है - जैसे यदि आप पुनरावृत्ति के लिए बैश 4 में उपयोग कर सकते हैं , लेकिन "तर्क सूची बहुत लंबा है" संदेश है मुमकिन)। ध्यान दें कि कमांड का हिस्सा स्क्रिप्ट या फ़ंक्शन के पहले तर्क को दर्शाता है। आपको किसी अन्य चर या तर्क विनिर्देश का उपयोग करने या यह सुनिश्चित करने की आवश्यकता हो सकती है कि एक तर्क पास किया जा रहा हैforfindfind -print0 | xargs -0for d in $SOMEFOLDER/*/-type d**shopt -s globstar${1}${d##*/}$1
जब तक कि अगली सूचना तक

2
@DennisWilliamson साझा करने के लिए बहुत बहुत धन्यवादकिसी भी भविष्य के पाठकों के लिए, जो आश्चर्यचकित करने लगते हैं कि यह काम क्यों नहीं कर रहा है या मैं यहां केवल बेवकूफ हूं । ऊपर उत्तर में माना गया है कि इसमें शामिल है । मुझे वह हिस्सा याद आ गया। मेरा उपयोग मामला: - वर्क्स 😉$1the path from which last component is to be taken outtarget_path='/home/user/dir1/dir2/dir3/'; target_path="${target_path%/}"; last_component=${target_path##*/}; echo $last_component
विनय विस्स

2
कैसे और क्यों ${1##*/} काम करता है की व्याख्या के लिए यहाँ देखें : unix.stackexchange.com/a/171786/15070
मैथ्यू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.