2008-09-24 14 views
300

"/foo/fizzbuzz.bar" जैसे स्ट्रिंग फ़ाइल पथ को देखते हुए, मैं स्ट्रिंग के केवल "fizzbuzz" हिस्से को निकालने के लिए बैश का उपयोग कैसे करूं? basename आदेश परमैं बैश में पथ स्ट्रिंग से फ़ाइल प्रत्यय और पथ भाग को कैसे हटा सकता हूं?

उत्तर

408

यहाँ कैसे बैश में # और% ऑपरेटरों के साथ यह करने के लिए है।

$ x="/foo/fizzbuzz.bar" 
$ y=${x%.bar} 
$ echo ${y##*/} 
fizzbuzz 

${x%.bar} भी एक डॉट या ${x%%.*} के बाद सब कुछ को हटाने के लिए पहले डॉट के बाद सब कुछ को दूर करने के ${x%.*} हो सकता है।

उदाहरण:

$ x="/foo/fizzbuzz.bar.quux" 
$ y=${x%.*} 
$ echo $y 
/foo/fizzbuzz.bar 
$ y=${x%%.*} 
$ echo $y 
/foo/fizzbuzz 

प्रलेखन Bash manual में पाया जा सकता। ${parameter%word} और ${parameter%%word} पिछला भाग मिलान अनुभाग देखें।

+0

मैंने इसका उपयोग करके समाप्त कर दिया क्योंकि यह सबसे लचीला था और कुछ अन्य समान चीजें भी थीं जो मैं करना चाहता था और यह अच्छी तरह से किया। –

+0

यह शायद पोस्ट किए गए सभी उत्तरों का सबसे लचीला है, लेकिन मुझे लगता है कि बेसनाम और डायरनाम कमांड का सुझाव देने वाले उत्तरों के कुछ भी ध्यान देने योग्य हैं। यदि आपको किसी अन्य फैंसी पैटर्न मिलान की आवश्यकता नहीं है तो वे सिर्फ चाल हो सकते हैं। – mgadda

+3

इसे $ {x% .bar} कहा जाता है? मैं इसके बारे में और जानना चाहता हूं। – Basil

170

देखो:

NAME=`basename /foo/fizzbuzz.bar .bar` 
+6

शायद वर्तमान में प्रस्तावित समाधानों में से सबसे सरल ... हालांकि मैं बैकटीक्स के बजाय $ (...) का उपयोग करता हूं। –

+6

सरल लेकिन एक निर्भरता जोड़ता है (एक बड़ा या अजीब नहीं, मैं मानता हूं)। इसे प्रत्यय को भी जानने की जरूरत है। –

+0

और अंत में कुछ भी हटाने के लिए इस्तेमाल किया जा सकता है, मूल रूप से यह केवल अंत से एक स्ट्रिंग हटाने को करता है। – Smar

12

शुद्ध बैश रास्ता:

~$ x="/foo/bar/fizzbuzz.bar.quux.zoom"; 
~$ y=${x/\/*\//}; 
~$ echo ${y/.*/}; 
fizzbuzz 

इस कार्यशीलता के तहत "पैरामीटर विस्तार" आदमी पार्टी पर समझाया गया है। गैर बाश के तरीके बहुत अधिक हैं: अजीब, perl, sed और इतने पर।

संपादित करें: प्रत्यय फ़ाइल में डॉट्स के साथ काम करता है और प्रत्यय (एक्सटेंशन) पता करने की जरूरत नहीं है, लेकिन नाम अपने आप में डॉट्स के साथ काम नहीं करता है।

7

basename और dirname कार्य हैं क्या आप के बाद कर रहे हैं:

mystring=/foo/fizzbuzz.bar 
echo basename: $(basename $mystring) 
echo basename + remove .bar: $(basename $mystring .bar) 
echo dirname: $(dirname $mystring) 

उत्पादन है:

basename: fizzbuzz.bar 
basename + remove .bar: fizzbuzz 
dirname: /foo 
3

basename का उपयोग करना मानता है कि आप जानते हैं कि फ़ाइल एक्सटेंशन क्या है, है ना?

और मेरा मानना ​​है कि विभिन्न नियमित अभिव्यक्ति सुझाव एक फ़ाइल नाम से सामना नहीं करते हैं जिसमें एक से अधिक "।"

निम्नलिखित डबल डॉट्स से निपटने के लिए प्रतीत होता है। ओह, और फ़ाइल नाम, जिनमें शामिल है एक "/" खुद को (बस के लिए kicks)

पास्कल व्याख्या करने के लिए, "क्षमा करें यह स्क्रिप्ट है इतने लंबे समय के। मैं इसे कम करने के लिए समय नहीं था"


    #!/usr/bin/perl 
    $fullname = $ARGV[0]; 
    ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/; 
    ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/; 
    print $basename . "\n"; 
+0

यह अच्छा और मजबूत –

2

यदि आप अन्य पदों में सुझाए गए बेसनाम का उपयोग नहीं कर सकते हैं, तो आप हमेशा sed का उपयोग कर सकते हैं। यहां एक (बदसूरत) उदाहरण है। यह सबसे महान नहीं है, लेकिन यह वांछित स्ट्रिंग निकालने और वांछित स्ट्रिंग के साथ इनपुट को बदलकर काम करता है।

echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g' 

जो तुम उत्पादन

fizzbuzz

+0

है हालांकि यह मूल प्रश्न का उत्तर है, लेकिन यह आदेश तब उपयोगी होता है जब मेरे पास स्क्रीन पर प्रिंट करने के लिए आधार नाम निकालने के लिए फ़ाइल में पथों की रेखाएं होती हैं। –

0

basename मिल जाएगा कि, पथ को हटा करता है। यदि दिया गया हो तो यह प्रत्यय को भी हटा देगा और यदि यह फ़ाइल के प्रत्यय से मेल खाता है लेकिन आपको आदेश देने के लिए प्रत्यय को जानने की आवश्यकता होगी। अन्यथा आप एमवी का उपयोग कर सकते हैं और पता लगा सकते हैं कि नया नाम कुछ और तरीका होना चाहिए।

2

सुझाए गए पर्ल समाधान से सावधान रहें: यह पहले बिंदु के बाद कुछ भी हटा देता है।

$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}' 
some 

आप पर्ल के साथ यह करने के लिए चाहते हैं, यह काम करता है:

$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}' 
some.file.with 

लेकिन अगर आप बैश उपयोग कर रहे हैं, y=${x%.*} (या basename "$x" .ext अगर आप एक्सटेंशन जानते हैं) के साथ समाधान बहुत सरल कर रहे हैं।

for file in *; do 
    ext=${file##*.} 
    fname=`basename $file $ext` 

    # Do things with $fname 
done; 

इस फाइल एक्सटेंशन का कोई एक प्रायोरी ज्ञान की आवश्यकता है और सामने भी काम करता है आप एक फ़ाइल नाम उस में डॉट्स है कि जब है फ़ाइल नाम (यह की:

10

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

+1

उत्कृष्ट जवाब! विस्तार को एक बहुत ही साफ तरीके से हटा देता है, लेकिन यह इसे हटा नहीं देता है। फ़ाइल नाम के अंत में। – metrix

+1

@ मेट्रिक्स बस "।" जोड़ें $ ext से पहले, यानी: 'fname = \' बेसनाम $ फ़ाइल। $ ext \ '' –

28

शुद्ध बैश, दो अलग-अलग अभियानों में किया:

  1. एक पथ-स्ट्रिंग से पथ निकालें:

    base=${file%.*} 
    #${base} is now 'file'. 
    
    :

    path=/foo/bar/bim/baz/file.gif 
    
    file=${path##*/} 
    #$file is now 'file.gif' 
    
  2. एक पथ-स्ट्रिंग से एक्सटेंशन निकालें

1

टी का मिश्रण दूसरी टॉप रेटेड जवाब के साथ सेशन रेटेड जवाब पूरा पथ के बिना फ़ाइल नाम पाने के लिए:

$ x="/foo/fizzbuzz.bar.quux" 
$ y=(`basename ${x%%.*}`) 
$ echo $y 
fizzbuzz 
0

जानकारी आप Bash manual में पा सकते हैं, भाग मिलान अनुभाग अनुगामी में ${parameter%word} और ${parameter%%word} के लिए देखो।

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