इस तरह के एक स्ट्रिंग फ़ाइल पथ को देखते हुए /foo/fizzbuzz.bar
, मैं कैसे fizzbuzz
कहा स्ट्रिंग के सिर्फ हिस्से को निकालने के लिए बैश का उपयोग करेगा ?
इस तरह के एक स्ट्रिंग फ़ाइल पथ को देखते हुए /foo/fizzbuzz.bar
, मैं कैसे fizzbuzz
कहा स्ट्रिंग के सिर्फ हिस्से को निकालने के लिए बैश का उपयोग करेगा ?
जवाबों:
यहाँ यह बैश में # और% ऑपरेटरों के साथ कैसे करना है।
$ 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
दस्तावेज को बाश मैनुअल में पाया जा सकता है । भाग मिलान अनुभाग के लिए देखें ${parameter%word}
और ${parameter%%word}
अनुगामी करें।
बेसन कमांड को देखें:
NAME="$(basename /foo/fizzbuzz.bar .bar)"
बेसनेम का उपयोग करके मैंने इसे प्राप्त करने के लिए निम्नलिखित का उपयोग किया:
for file in *; do
ext=${file##*.}
fname=`basename $file $ext`
# Do things with $fname
done;
इसके लिए फ़ाइल एक्सटेंशन का कोई प्राथमिक ज्ञान नहीं है और तब भी काम करता है जब आपके पास एक फ़ाइल नाम है जिसमें यह फ़ाइल नाम है (इसके विस्तार के सामने); basename
हालांकि इसे कार्यक्रम की आवश्यकता होती है , लेकिन यह GNU कोरुटिल्स का हिस्सा है, इसलिए इसे किसी भी डिस्ट्रो के साथ जहाज करना चाहिए।
fname=`basename $file .$ext`
शुद्ध बैश रास्ता:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
इस कार्यक्षमता को "पैरामीटर विस्तार" के तहत मैन बैश पर समझाया गया है। नॉन बैश तरीके लाजिमी हैं: awk, perl, sed और इतने पर।
संपादित करें: फ़ाइल प्रत्यय में डॉट्स के साथ काम करता है और प्रत्यय (विस्तार) को जानने की आवश्यकता नहीं है, लेकिन नाम में डॉट्स के साथ काम नहीं करता है।
बेसनेम और 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
mystring=$1
के बजाय वर्तमान निरंतर मूल्य (जो कई बार चेतावनी को दबाने होगा, रिक्त स्थान / ग्लोब वर्ण / आदि को रोकने के लिए नहीं कुछ किया जा रहा है), और समस्या का पता लगाने में यह पाता?
echo "basename: $(basename "$mystring")"
- इस तरह से यदि mystring='/foo/*'
आप खत्म होने के बाद*
वर्तमान निर्देशिका में फ़ाइलों की सूची के साथ प्रतिस्थापित नहीं करते हैं । basename
का उपयोग करते हुए basename
मान लिया गया है आप जानते हैं कि क्या फाइल एक्सटेंशन है, यह नहीं है कि यह?
और मेरा मानना है कि विभिन्न नियमित अभिव्यक्ति सुझाव एक फ़ाइलनाम के साथ सामना नहीं करते हैं जिसमें एक से अधिक "हैं।"
निम्नलिखित डबल डॉट्स के साथ सामना करने के लिए लगता है। ओह, और फ़ाइल नाम जिसमें "/" खुद है (सिर्फ किक के लिए)
पास्कल को परोपकार करने के लिए, "क्षमा करें कि यह स्क्रिप्ट इतनी लंबी है। मेरे पास इसे छोटा करने का समय नहीं था"
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
इस उत्तर में इस्तेमाल POSIX अनुरूप सिंटैक्स के अलावा ,
basename string [suffix]
जैसे की
basename /foo/fizzbuzz.bar .bar
GNUbasename
एक और वाक्यविन्यास का समर्थन करता है:
basename -s .bar /foo/fizzbuzz.bar
उसी परिणाम के साथ। अंतर और फायदा यह है कि -s
इसका मतलब है -a
, जो कई तर्कों का समर्थन करता है:
$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar
यह भी -z
विकल्प का उपयोग करके NUL बाइट्स के साथ आउटपुट को अलग करके फ़ाइलनाम-सुरक्षित बनाया जा सकता है , उदाहरण के लिए इन फ़ाइलों में रिक्त स्थान, newlines और ग्लोब वर्ण (द्वारा उद्धृत ls
):
$ ls has*
'has'$'\n''newline.bar' 'has space.bar' 'has*.bar'
एक सरणी में पढ़ना:
$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")
readarray -d
बैश 4.4 या नए की आवश्यकता है। पुराने संस्करणों के लिए, हमें लूप करना होगा:
while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)
यदि आप अन्य पोस्ट में सुझाए गए बेसनेम का उपयोग नहीं कर सकते हैं, तो आप हमेशा सेड का उपयोग कर सकते हैं। यहाँ एक (बदसूरत) उदाहरण है। यह सबसे बड़ा नहीं है, लेकिन यह वांछित स्ट्रिंग को निकालने और वांछित स्ट्रिंग के साथ इनपुट को बदलने के द्वारा काम करता है।
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
जो आपको आउटपुट मिलेगा
fizzbuzz
सुझाए गए पर्ल समाधान से सावधान रहें: यह पहली डॉट के बाद कुछ भी हटा देता है।
$ 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
यदि आप विस्तार जानते हैं) के समाधान बहुत सरल हैं।
बेसन ऐसा करता है, जो रास्ता निकालता है। यह दिए गए प्रत्यय को हटा देगा और यदि यह फ़ाइल के प्रत्यय से मेल खाता है, लेकिन आपको कमांड को देने के लिए प्रत्यय को जानना होगा। अन्यथा आप एमवी का उपयोग कर सकते हैं और यह पता लगा सकते हैं कि नया नाम किसी और तरीके से क्या होना चाहिए।
पूर्ण-पथ के बिना फ़ाइल नाम प्राप्त करने के लिए दूसरे-टॉप-रेटेड उत्तर के साथ शीर्ष-रेटेड उत्तर को संयोजित करना:
$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz
${parameter%word}
और${parameter%%word}
भाग मिलान अनुभाग अनुगामी में।