मैं शेल स्क्रिप्ट में फ़ाइल नाम का एक्सटेंशन कैसे हटा सकता हूं?


144

निम्नलिखित कोड में क्या गलत है?

name='$filename | cut -f1 -d'.''

जैसा कि, मुझे शाब्दिक स्ट्रिंग मिलता है $filename | cut -f1 -d'.', लेकिन यदि मैं उन उद्धरणों को हटा देता हूं तो मुझे कुछ भी नहीं मिलता है। इस बीच, टाइपिंग

"test.exe" | cut -f1 -d'.'

एक शेल में मुझे वह आउटपुट मिलता है जो मैं चाहता हूं test,। मुझे पहले से ही पता $filenameहै कि सही मूल्य सौंपा गया है। मैं जो करना चाहता हूं वह एक्सटेंशन के बिना फ़ाइल नाम के एक चर को असाइन करना है।


6
basename $filename .exeवही काम करेगा। यह मानते हुए कि आप हमेशा जानते हैं कि आप किस विस्तार को हटाना चाहते हैं।
एमपी

6
@ एमपीई, आपका मतलब है basename "$filename" .exe। अन्यथा रिक्त स्थान वाले फाइलनाम बुरी खबर होगी।
चार्ल्स डफी

जवाबों:


113

जब आप स्क्रिप्ट / कमांड में कमांड निष्पादित करना चाहते हैं तो आपको कमांड प्रतिस्थापन सिंटैक्स का उपयोग करना चाहिए $(command)

तो आपकी लाइन होगी

name=$(echo "$filename" | cut -f 1 -d '.')

कोड स्पष्टीकरण:

  1. echoचर का मान प्राप्त करें $filenameऔर इसे मानक आउटपुट पर भेजें
  2. हम फिर आउटपुट को पकड़ते हैं और उसे पाइप करते हैं cut कमांड पर
  3. का cutउपयोग करेगा। स्ट्रिंग को सेगमेंट में काटने के लिए सीमांकक (विभाजक के रूप में भी जाना जाता है) के रूप में और -fहम यह चुनते हैं कि हम किस सेगमेंट में आउटपुट चाहते हैं
  4. फिर $()कमांड प्रतिस्थापन को आउटपुट मिलेगा और इसके मूल्य को वापस करेगा
  5. लौटाया गया मान नामित चर को सौंपा जाएगा name

ध्यान दें कि यह चर का भाग पहली अवधि तक देता है .:

$ filename=hello.world
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello.hello.hello
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello
$ echo "$filename" | cut -f 1 -d '.'
hello

धन्यवाद। मैंने यह भी देखा कि मुझे इको कमांड का उपयोग करने की आवश्यकता है। name =echo $filename | cut -f1 -d'.'
mimicocotopus

17
बैकटिक्स POSIX द्वारा पदावनत किए जाते हैं, $()पसंद किए जाते हैं।
जोर्डन

3
कुछ पात्रों में प्राप्त करने के लिए फोर्किंग और पाइपिंग सबसे खराब समाधान है।
जेन्स

39
इस उत्तर के साथ समस्या यह है कि यह माना जाता है कि इनपुट स्ट्रिंग में केवल एक डॉट है ... @chepner के पास एक बेहतर समाधान है ... नाम = $ {फ़ाइल नाम%। *}
स्कॉट स्टेंसलैंड

4
यह उत्तर शुरुआती की विशेषता है और इसे फैलाना नहीं चाहिए। के रूप में द्वारा chepner के जवाब वर्णित अंतर्निहित तंत्र का प्रयोग करें
neric

258

आप पैरामीटर विस्तार का भी उपयोग कर सकते हैं:

$ filename=foo.txt
$ echo "${filename%.*}"
foo

6
यहाँ कमांड का स्पष्टीकरण: gnu.org/software/bash/manual/html_node/…
कार्लोस रॉबल्स

1
और यहाँ मैं उपयोग करने वाला था echo -n "This.File.Has.Periods.In.It.txt" | awk -F. '{$NF=""; print $0}' | tr ' ' '.' | rev | cut -c 2- | rev। धन्यवाद।
user208145

1
क्या यह कई एक्सटेंशन जैसी फ़ाइलों के साथ काम करता है image.png.gz?
हॉकर 65

11
%.*केवल अंतिम एक्सटेंशन को हटा देगा; यदि आप सभी एक्सटेंशन हटाना चाहते हैं , तो उपयोग करें %%.*
chepner

1
यह स्वीकृत उत्तर की तुलना में बेहतर तरीके से काम करता है। यदि फ़ाइल में एक से अधिक बिंदु हैं, तो यह केवल अंतिम एक्सटेंशन को बंद कर देता है, जबकि कट पहले डॉट के बाद सब कुछ हटा देता है।
डेल एंडरसन

117

यदि आप एक्सटेंशन जानते हैं, तो आप बेसन का उपयोग कर सकते हैं

$ basename /home/jsmith/base.wiki .wiki
base

मैं बस कैसे निकाल सकता हूं .wikiऔर समाप्त कर सकता हूं /home/jsmith/base?
गेब्रियल स्टेपल्स

अपडेट: उत्तर: देखें stackoverflow.com/a/32584935/4561887 । अच्छी तरह से काम!
गेब्रियल स्टेपल्स

20

यदि आपके फ़ाइल नाम में एक डॉट (एक्सटेंशन के अलावा) है तो इसका उपयोग करें:

echo $filename | rev | cut -f 2- -d '.' | rev

1
मैं मध्य घूमना भूल गया, लेकिन एक बार मैंने इसे देखा, यह बहुत अच्छा था!
परम पूज्य

यह -sदिए गए एक विकल्प के साथ और भी बेहतर है cut, ताकि जब भी फ़ाइल नाम में कोई डॉट न हो तो यह एक खाली स्ट्रिंग लौटाए।
हिब्बू57

1
यह मेरी राय में स्वीकृत उत्तर होना चाहिए, क्योंकि यह उन में डॉट्स के साथ पथ पर काम करता है, जिसमें छिपी हुई फाइलें डॉट के साथ शुरू होती हैं, या यहां तक ​​कि कई एक्सटेंशन के साथ फाइल भी होती हैं।
टिम क्राय

20
file1=/tmp/main.one.two.sh
t=$(basename "$file1")                        # output is main.one.two.sh
name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two
name=$(echo "$t" | sed -e 's/\.[^.]*$//')     # output is main.one.two

जो भी आप चाहते हैं का उपयोग करें। यहाँ मैं मानता हूं कि .पाठ के बाद अंतिम (डॉट) विस्तार है।


6
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

आउटपुट:

/tmp/foo.bar.gz /tmp/foo.bar

ध्यान दें कि केवल अंतिम एक्सटेंशन हटा दिया गया है।


3

मेरी सिफारिश का उपयोग करना है basename
यह उबंटू में डिफ़ॉल्ट रूप से, नेत्रहीन सरल कोड है और अधिकांश मामलों से निपटता है।

रिक्त स्थान और मल्टी-डॉट / सब-एक्सटेंशन से निपटने के लिए यहां कुछ उप-मामले हैं:

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

यह आमतौर पर पहले से विस्तार से छुटकारा पा लेता है ., लेकिन हमारे ..रास्ते में विफल रहता है

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

यहाँ एक महत्वपूर्ण नोट है:

मैंने रिक्त स्थान से निपटने के लिए दोहरे उद्धरण चिह्नों का उपयोग किया। $ बोली लगाने के कारण एकल उद्धरण पास नहीं होगा। बैश असामान्य है और विस्तार के कारण "दूसरा" पहला "उद्धरण" पढ़ता है।

हालाँकि, आपको अभी भी सोचने की ज़रूरत है .hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

अपेक्षित "" परिणाम नहीं। इसे उपयोग करने के लिए $HOMEया /home/user_path/
फिर से बैश करने के कारण "असामान्य" है और "~" का विस्तार न करें (bash BashPitashes के लिए खोज करें)

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'


1

जैसा कि शेपनर जवाब की टिप्पणी में हॉकर 65 ने कहा है, सबसे अधिक मतदान समाधान न तो कई एक्सटेंशनों का ध्यान रखता है (जैसे कि filename.tar.gz), और न ही शेष पथ में डॉट्स (जैसे यह .path / के साथ) .dots / in.path.name)। एक संभावित समाधान है:

a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)

यह एक नाम है "tar.gz" जो कि फ़ाइल नाम में पहले बिंदु से पहले वर्णों का चयन करके पथ की गिनती नहीं करता है। एक शायद इस तरह से एक्सटेंशन स्ट्रिप नहीं करना चाहता।
फ्रात्ज

0

आपके कोड के साथ दो समस्याएं:

  1. आप चर में उत्पन्न स्ट्रिंग को उत्पन्न करने वाले कमांड को घेरने के लिए `(बैक टिक) के बजाय एक (टिक) का उपयोग करते हैं।
  2. आपने "कट" कमांड में पाइप में वेरिएबल "$ फाइलन" को "इको" नहीं किया।

मैं आपके कोड को "name =` echo $ filename | cut -f 1 -d 'में बदल दूंगा।' `", जैसा कि नीचे दिखाया गया है (फिर से, नाम चर परिभाषा के आसपास के पीछे की टिक पर ध्यान दें):

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.