আমি কীভাবে কোনও শেল স্ক্রিপ্টে ফাইলের নামের এক্সটেনশন সরিয়ে ফেলতে পারি?


143

নিম্নলিখিত কোডটিতে কী ভুল?

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

যেমনটি হ'ল আমি আক্ষরিক স্ট্রিংটি $filename | cut -f1 -d'.'পাই তবে আমি উদ্ধৃতিগুলি সরিয়ে ফেললে আমি কিছুই পাই না। এদিকে, টাইপিং

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

একটি শেল আমাকে আমার আউটপুট দেয় test,। আমি ইতিমধ্যে জানি $filenameসঠিক মান নির্ধারিত হয়েছে। আমি যা করতে চাই তা হল কোনও এক্সটেনশন ছাড়াই ফাইলের একটি ভেরিয়েবলকে বরাদ্দ করা।


6
basename $filename .exeএকই জিনিস করতে হবে। এটি ধরে নেওয়া হচ্ছে আপনি সর্বদা জানেন আপনি কী এক্সটেনশনটি সরাতে চান know
— এমপি

6
@mpe, আপনি কি বলতে চান 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

ধন্যবাদ। আমি এও লক্ষ্য করেছি যে আমার ইকো কমান্ড ব্যবহার করা দরকার। নাম =echo $filename | cut -f1 -d'.'
— মিমিকোকোটপাস

17
ব্যসটিকগুলি পসিক্স দ্বারা অবহিত করা হয়, $()পছন্দ করা হয়।
— jordanm

3
কয়েকটি চরিত্রটি পেতে ফোর্কিং এবং পাইপিং কল্পনা করার মতো সবচেয়ে খারাপ সমাধান।
— জেনস

39
এই উত্তরের সমস্যাটি হ'ল এটি অনুমান করে যে ইনপুট স্ট্রিংয়ের কেবলমাত্র একটি বিন্দু রয়েছে ... নীচের চ্যান্টারের আরও অনেক ভাল সমাধান রয়েছে ... নাম = $ {ফাইলের নাম% * *}
— স্কট স্টেনস্ল্যান্ড

4
এই উত্তরটি প্রাথমিকদের বৈশিষ্ট্য এবং এটি ছড়িয়ে দেওয়া উচিত নয়। চেপনারের উত্তর দ্বারা বর্ণিত বিল্টিন মেকানিজমটি ব্যবহার করুন
— স্নাতক

257

আপনি প্যারামিটার সম্প্রসারণও ব্যবহার করতে পারেন:

$ 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। ধন্যবাদ।
— ব্যবহারকারী 208145

1
এটি কি একাধিক এক্সটেনশানযুক্ত ফাইলগুলির সাথে কাজ করে image.png.gz?
— হককার 65

11
%.*শুধুমাত্র শেষ এক্সটেনশন সরিয়ে ফেলবে; আপনি যদি সমস্ত এক্সটেনশান মুছে ফেলতে চান তবে ব্যবহার করুন %%.*।
— চিপনার

1
এটি গ্রহণযোগ্য উত্তরের চেয়ে আরও ভালভাবে কাজ করছে বলে মনে হচ্ছে। ফাইলটিতে একাধিক বিন্দু থাকলে এটি কেবল সর্বশেষ এক্সটেনশনটি সরিয়ে দেয়, যখন কাটাটি প্রথম বিন্দুর পরে সমস্ত কিছু সরিয়ে দেয়।
— ডেল অ্যান্ডারসন

117

আপনি যদি এক্সটেনশনটি জানেন তবে আপনি বেস নামটি ব্যবহার করতে পারেন

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

আমি কীভাবে সরাতে পারি .wikiএবং শেষ করতে পারি /home/jsmith/base?
— গ্যাব্রিয়েল স্ট্যাপলস

আপডেট: উত্তর: স্ট্যাকওভারফ্লো . com/a/32584935/4561887 দেখুন । পুরোপুরি কাজ করে!
— গ্যাব্রিয়েল স্ট্যাপলস

20

যদি আপনার ফাইলের নামটিতে একটি বিন্দু থাকে (এক্সটেনশনের একটি বাদে) তবে এটি ব্যবহার করুন:

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

1
আমি মাঝের রেভকে ভুলে গিয়েছিলাম, কিন্তু একবার এটি দেখেছি, এটি দুর্দান্ত ছিল!
— সুপ্রিম পূবা

-sদেওয়া বিকল্পের সাথে এটি আরও ভাল cut, যাতে যখনই ফাইলের নামটিতে কোনও বিন্দু না থাকে এটি খালি স্ট্রিংটি দেয়।
— Hibou57

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

মনে রাখবেন যে শুধুমাত্র শেষ এক্সটেনশন সরানো হয়েছে is


3

আমার সুপারিশটি ব্যবহার করা basename।
এটি উবুন্টুতে ডিফল্টরূপে, ভিজ্যুয়ালি সহজ কোড এবং বেশিরভাগ ক্ষেত্রে মোকাবেলা করা হয়।

শূন্যস্থান এবং মাল্টি-ডট / সাব-এক্সটেনশন মোকাবেলার জন্য এখানে কয়েকটি উপ-কেস রয়েছে:

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

এটি সাধারণত প্রথম থেকেই প্রসার থেকে মুক্তি পায় .তবে আমাদের ..পথে ব্যর্থ হয়

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

এখানে একটি গুরুত্বপূর্ণ নোট:

আমি স্পেসগুলি মোকাবেলায় ডাবল কোটসের ভিতরে ডাবল কোট ব্যবহার করেছি। একক উদ্ধৃতি tex টেক্সট করার কারণে পাস হবে না $ বাশ অস্বাভাবিক এবং প্রসারণের কারণে "দ্বিতীয়" প্রথম "উদ্ধৃতি" পড়ে।

তবে, আপনার এখনও চিন্তা করা দরকার .hidden_files

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

প্রত্যাশিত ফলাফল নয়। এটি ব্যবহারে ঘটানোর জন্য $HOMEবা /home/user_path/
আবার ব্যাশটি "অস্বাভাবিক" এবং "~" প্রসারিত করবেন না (ব্যাশের বাশপিটফলগুলি অনুসন্ধান করুন)

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

1
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

আউটপুট:

program

৫ বছর আগে স্টিভেন পেনি যে উত্তর দিয়েছিলেন তা থেকে এটি কীভাবে আলাদা?
— gniourf_gniourf

1

চ্যাপার উত্তরের মন্তব্যে হককার 65 দ্বারা নির্দেশিত হিসাবে, সর্বাধিক ভোট দেওয়া সমাধানটি একাধিক এক্সটেনশান (যেমন ফাইলের নাম.আর্ট্রিজেড), না বাকী পথের বিন্দু (যেমন এই.পথ / সহ) যত্ন করে না .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. আপনি "কাটা" কমান্ডের পাইপে "ভেরিয়েবল" ফাইলনাম "" প্রতিধ্বনি "করেন নি।

আমি আপনার কোডটি "নাম =` প্রতিধ্বনি $ ফাইলের নাম | কাট -f 1 -d 'এ পরিবর্তন করব।' `", নীচে প্রদর্শিত হিসাবে (আবার, নামের পরিবর্তনশীল সংজ্ঞাটি ঘিরে পিছনের টিকগুলি লক্ষ্য করুন):

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.