বাশ-এ ফাইলের নাম এবং এক্সটেনশানটি বের করুন


2104

আমি ফাইলের নাম (এক্সটেনশন ছাড়াই) এবং এক্সটেনশনটি আলাদাভাবে পেতে চাই।

আমি এখনও অবধি সবচেয়ে ভাল সমাধানটি খুঁজে পেয়েছি:

NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`

এটি ভুল কারণ ফাইলের নামটিতে একাধিক .অক্ষর থাকলে এটি কাজ করে না । পারেন, ধরুন, আমি করি a.b.js, এটা বিবেচনা করব aএবং b.jsপরিবর্তে a.bএবং js

পাইথনে এটি দিয়ে সহজেই করা যায়

file, ext = os.path.splitext(path)

তবে আমি যদি সম্ভব হয় তবে কেবলমাত্র এটির জন্য পাইথন দোভাষীকে গুলি না করাই পছন্দ করব।

আরও ভাল ধারণা?


এই প্রশ্নটি এই ব্যাশ কৌশল এবং অন্যান্য বেশ কয়েকটি সম্পর্কিত সম্পর্কিত ব্যাখ্যা করে।
jjclarkson

28
নীচের দুর্দান্ত উত্তরগুলি প্রয়োগ করার সময়, আপনার ভেরিয়েবলের মতো এখানে পেস্ট করবেন না যেমন আমি এখানে ভুল দেখায় :extension="{$filename##*.}" যেমন আমি কিছুক্ষণ করেছি! $কোঁকড়ানো বাহিরের বাইরে সরান : ডান: extension="${filename##*.}"
ক্রিস কে

4
এটি স্পষ্টত একটি তুচ্ছ সমস্যা এবং আমার জন্য নীচের উত্তরগুলি সম্পূর্ণ সঠিক কিনা তা বলা মুশকিল। এটি আশ্চর্যজনক যে এটি (বা) এস-এ কোনও বিল্ট ইন অপারেশন নয় (উত্তরগুলি প্যাটার্ন ম্যাচিংয়ের সাহায্যে ফাংশনটি বাস্তবায়িত করে বলে মনে হচ্ছে)। পরিবর্তে আমি পাইথনের os.path.splitextউপরের হিসাবে ব্যবহার করার সিদ্ধান্ত নিয়েছি ...
পিটার গিবসন

1
হিসাবে এক্সটেনশন প্রতিনিধিত্ব আছে প্রকৃতি একটি ফাইলের, একটি হল জাদু কমান্ড তাঁর প্রকৃতি এবং প্রস্তাব ঐশ্বরিক ফাইল পরীক্ষা মান এক্সটেনশন । দেখতে আমার উত্তর
এফ Hauri

2
প্রশ্নটি প্রথমে সমস্যাযুক্ত কারণ .. সাধারণভাবে ওএস এবং ইউনিক্স ফাইল-সিস্টেমের দৃষ্টিকোণ থেকে, ফাইল এক্সটেনশন বলে কোনও জিনিস নেই। ব্যবহার করে একটি "." পৃথক অংশগুলিতে একটি মানব সম্মেলন , এটি যতক্ষণ কাজ করে যতক্ষণ না মানুষ এটি অনুসরণ করতে সম্মত হন। উদাহরণস্বরূপ, 'টার' প্রোগ্রামের সাথে, "টার" দিয়ে আউটপুট ফাইলের নাম দেওয়ার সিদ্ধান্ত নেওয়া যেতে পারে। একটি ".তার" প্রত্যয়ের পরিবর্তে উপসর্গ - "সামারডির.টার" পরিবর্তে "তার.সোমাদির" প্রদান করা। এর জন্য কোনও "জেনারেল, সর্বদা কাজ করে না" এর সমাধান নেই - আপনাকে এমন কোড লিখতে হবে যা আপনার নির্দিষ্ট চাহিদা এবং প্রত্যাশিত ফাইলের নামের সাথে মেলে।
সিএম

উত্তর:


3497

প্রথমে পাথ ছাড়াই ফাইলের নাম পান:

filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"

বিকল্পভাবে, আপনি 'এর পরিবর্তে' শেষের '/' দিকে মনোনিবেশ করতে পারেন। আপনার অনির্দেশ্য ফাইল এক্সটেনশন থাকলেও যা কাজ করবে:

filename="${fullfile##*/}"

আপনি ডকুমেন্টেশন চেক করতে চাইতে পারেন:


85
সম্পূর্ণ বৈশিষ্ট্য সেটটির জন্য gnu.org/software/bash/manual/html_node/… দেখুন ।
ডি.শ্যাওলি

24
"$ ফুলফিলি" তে কিছু উদ্ধৃতি যুক্ত করুন, বা আপনি ফাইলের নাম ভাঙার ঝুঁকি নিয়ে যাবেন।
লুুনাথ

47
হেক, আপনি করতে পারে এমনকি লেখার ফাইলের নাম = "$ {fullfile ## * /}" এবং এড়ানোর একটি অতিরিক্ত কলিংbasename
ephemient

45
ফাইলটির কোনও এক্সটেনশন না থাকলে এই "সমাধান" কাজ করে না - পরিবর্তে পুরো ফাইলের নাম আউটপুট হয়, এটি এক্সটেনশন ছাড়াই ফাইল সর্বব্যাপী বিবেচনা করে যথেষ্ট খারাপ।
এনসিসিসি

43
এক্সটেনশন ছাড়া ফাইলের নাম মোকাবেলার জন্য ত্রুটিমুক্ত: extension=$([[ "$filename" = *.* ]] && echo ".${filename##*.}" || echo '')। মনে রাখবেন যদি একটি এক্সটেনশন হয় বর্তমান, এটা প্রাথমিক সহ ফেরত পাঠানো হবে ., যেমন .txt
mklement0

682
~% FILE="example.tar.gz"

~% echo "${FILE%%.*}"
example

~% echo "${FILE%.*}"
example.tar

~% echo "${FILE#*.}"
tar.gz

~% echo "${FILE##*.}"
gz

আরও তথ্যের জন্য, ব্যাশ ম্যানুয়ালটিতে শেল প্যারামিটার সম্প্রসারণ দেখুন ।


22
.Tar.gz হিসাবে ফাইলনামের "এক্সটেনশন" অংশে 2 টি বিন্দু থাকলে কী করবেন সে সম্পর্কে আপনি (সম্ভবত অনিচ্ছাকৃতভাবেই) দুর্দান্ত প্রশ্নটি উত্থাপন করেছেন ... আমি কখনই এই সমস্যাটি বিবেচনা করি নি এবং আমার সন্দেহ হয় যে এটি সামনে সমস্ত সম্ভাব্য বৈধ ফাইল এক্সটেনশনগুলি না জেনে সমাধানযোগ্য নয়।
rmeador

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

22
এটি লাক্ষিক ভিত্তিতে সমাধানযোগ্য নয়, আপনাকে ফাইলের প্রকারটি পরীক্ষা করতে হবে। আপনি একটি খেলা বলা ছিল, তা বিবেচনা dinosaurs.in.tarকরবেন এবং তোমাদের তা gzipped dinosaurs.in.tar.gz:)
porges

11
আপনি যদি পুরো পথে চলে যাচ্ছেন তবে এটি আরও জটিল হয়ে উঠবে। আমার একজনের একটি ছিল '।' পথের মাঝামাঝি একটি ডিরেক্টরিতে, তবে ফাইলের নামের কোনওটি নয়। "এ / বিসি / ডি / ই / ফাইলের নাম" উদাহরণস্বরূপ ".সি / ডি / ই / ফাইলের নাম"
ওয়াল্ট বিক্রেতারা

6
স্পষ্টত x.tar.gzকোনওর প্রসার নেই gzএবং ফাইলের নামটি x.tarহ'ল এটি। দ্বৈত বর্ধনের মতো কোনও জিনিস নেই। আমি বেশ নিশ্চিত যে বুস্ট :: ফাইল সিস্টেমটি সেভাবে পরিচালনা করে। (বিভক্ত পাথ, চেঞ্জ_ এক্সটেনশন ...) এবং এর আচরণটি যদি আমি ভুল না করি তবে পাইথনের উপর ভিত্তি করে।
v.oddou

429

সাধারণত আপনি ইতিমধ্যে এক্সটেনশনটি জানেন, তাই আপনি ব্যবহার করতে পারেন:

basename filename .extension

উদাহরণ স্বরূপ:

basename /path/to/dir/filename.txt .txt

এবং আমরা পেতে

filename

60
দ্বিতীয় দ্বিতীয় যুক্তিটি basenameহ'ল চোখের ওপেনার, টাই
মাইন্ড

10
এবং এই কৌশলটি ব্যবহার করে কীভাবে এক্সটেনশানটি এক্সট্রাক্ট করবেন? ;) অপেক্ষা কর! আমরা আসলে এটি সামনে জানি না।
টমাসজ গ্যান্ডোর

3
বলুন আপনার একটি জিপড ডিরেক্টরি রয়েছে যা হয় .zipবা দিয়ে শেষ হয় .ZIP। আপনি কি কিছু করতে পারে এমন কোন উপায় আছে basename $file {.zip,.ZIP}?
ডেনিস

8
যদিও এটি কেবল ওপিএস প্রশ্নের অংশের উত্তর দেয়, এটি গুগলে টাইপ করা প্রশ্নের উত্তর দেয়। :-) খুব চতুর!
sudo

1
সহজ এবং
পসিক্স

146

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

bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo "${FILENAME%%.*}"
somefile
bash-3.2$ echo "${FILENAME%.*}"
somefile.tar

এতে একটি সতর্কতা রয়েছে যদি আপনার ফাইলের নামটি ফর্মের হয় ./somefile.tar.gzতবে echo ${FILENAME%%.*}লোভের সাথে সবচেয়ে দীর্ঘতম মিলটি সরিয়ে ফেলবে .এবং আপনার খালি স্ট্রিংটি থাকবে।

(আপনি একটি অস্থায়ী পরিবর্তনশীল সহ এটিকে ঘিরে কাজ করতে পারেন:

FULL_FILENAME=$FILENAME
FILENAME=${FULL_FILENAME##*/}
echo ${FILENAME%%.*}

)


এই সাইটটি আরও ব্যাখ্যা করে।

${variable%pattern}
  Trim the shortest match from the end
${variable##pattern}
  Trim the longest match from the beginning
${variable%%pattern}
  Trim the longest match from the end
${variable#pattern}
  Trim the shortest match from the beginning

5
জোয়াকিমের উত্তরের চেয়ে অনেক সহজ তবে আমি সর্বদা পসিক্স পরিবর্তনশীল প্রতিস্থাপনটি খুঁজতে হবে। এছাড়াও, এটি ম্যাক্স ওএসএক্সে চলে যেখানে যেখানে cutনেই --complementএবং sedনেই -r
জাওয়াদস্যাক

72

ফাইলটির কোনও এক্সটেনশন না থাকলে বা ফাইলের নাম না থাকলে এটি কাজ করে বলে মনে হচ্ছে না। আমি যা ব্যবহার করছি তা এখানে; এটি কেবল বিল্টিনগুলি ব্যবহার করে এবং আরও বেশি (তবে সমস্ত নয়) প্যাথলজিকাল ফাইল নামগুলি পরিচালনা করে।

#!/bin/bash
for fullpath in "$@"
do
    filename="${fullpath##*/}"                      # Strip longest match of */ from start
    dir="${fullpath:0:${#fullpath} - ${#filename}}" # Substring from 0 thru pos of filename
    base="${filename%.[^.]*}"                       # Strip shortest match of . plus at least one non-dot char from end
    ext="${filename:${#base} + 1}"                  # Substring from len of base thru end
    if [[ -z "$base" && -n "$ext" ]]; then          # If we have an extension and no base, it's really the base
        base=".$ext"
        ext=""
    fi

    echo -e "$fullpath:\n\tdir  = \"$dir\"\n\tbase = \"$base\"\n\text  = \"$ext\""
done

এবং এখানে কিছু টেস্টকেস রয়েছে:

$ বেসনাম- এবং- এক্সটেনশন.শ / / হোম / আমি / / হোম / আমি / ফাইল / হোমে / মাই / ফাইলে.টার / হোম / মাই / ফাইলে.টার.gz / হোম / মাই / হিডেন / হোম / আমি / .hided.tar / home / me / ..।
/:
    দির = "/"
    বেস = ""
    ext = ""
/ হোম / ME /:
    দির = "/ হোম / আমি /"
    বেস = ""
    ext = ""
/ হোম / ME / ফাইল:
    দির = "/ হোম / আমি /"
    বেস = "ফাইল"
    ext = ""
/home/me/file.tar:
    দির = "/ হোম / আমি /"
    বেস = "ফাইল"
    অতিরিক্ত = "তার"
/home/me/file.tar.gz:
    দির = "/ হোম / আমি /"
    বেস = "file.tar"
    ext = "gz"
/home/me/.hidden:
    দির = "/ হোম / আমি /"
    বেস = "। লুকানো"
    ext = ""
/home/me/.hidden.tar:
    দির = "/ হোম / আমি /"
    বেস = "। লুকানো"
    অতিরিক্ত = "তার"
/ হোম / ME / ..:
    দির = "/ হোম / আমি /"
    বেস = ".."
    ext = ""
।
    দির = ""
    বেস = "।"
    ext = ""

2
পরিবর্তে dir="${fullpath:0:${#fullpath} - ${#filename}}"আমি প্রায়ই দেখেছি dir="${fullpath%$filename}"। এটি লিখতে সহজ। সত্যিকারের গতির পার্থক্য বা গোটচাস আছে কিনা তা নিশ্চিত নয়।
সন্দেহভাজন

2
এটি #! / বিন / বাশ ব্যবহার করে যা প্রায়শই ভুল। যদি সম্ভব হয় তবে #! / বিন / এস বা #! / Usr / bin / env বাশ পছন্দ করুন।
ভাল ব্যক্তি

@ শুভ ব্যক্তি: আমি জানি না কীভাবে এটি প্রায় সর্বদা ভুল: which bash-> /bin/bash; সম্ভবত এটি আপনার ডিস্ট্রো?
ভোলআরন

2
@ ভোলআরন - অনেকগুলি ডিস্ট্রো ব্যাশে / ইউএসআর / স্থানীয় / বিন / ব্যাশে রয়েছে ash ওএসএক্সে অনেকে / অপ্ট / লোকাল / বিন / ব্যাশে একটি আপডেট ব্যাশ ইনস্টল করেন। যেমন / বিন / ব্যাশটি ভুল এবং এটি খুঁজে পেতে কারওটি এনভিউ ব্যবহার করা উচিত। আরও ভাল / বিন / শ এবং পসিক্স কনস্ট্রাক্ট ব্যবহার করা। সোলারিস বাদে এটি পসিক্স শেল।
শুভ ব্যক্তি

2
@ গুডপারসন তবে আপনি যদি বাশ নিয়ে বেশি স্বাচ্ছন্দ্য বোধ করেন তবে কেন sh ব্যবহার করবেন? এটি কি বলার মতো নয়, যখন আপনি sh ব্যবহার করতে পারেন তখন কেন পার্ল ব্যবহার করবেন?
ভোলআরন

46

আপনি ব্যবহার করতে পারেন basename

উদাহরণ:

$ basename foo-bar.tar.gz .tar.gz
foo-bar

আপনাকে সেই এক্সটেনশনটির সাথে বেসনাম সরবরাহ করতে হবে যা সরিয়ে দেওয়া হবে, তবে আপনি যদি সর্বদা এটি সম্পাদন tarকরে থাকেন -zতবে আপনি জানেন কী এক্সটেনশন হবে .tar.gz

এটি আপনার যা করা উচিত তা করা উচিত:

tar -zxvf $1
cd $(basename $1 .tar.gz)

2
আমি মনে করি cd $(basename $1 .tar.gz).gz ফাইলগুলির জন্য কাজ করে। তবে প্রশ্নে তিনি উল্লেখ করেছেনArchive files have several extensions: tar.gz, tat.xz, tar.bz2
এসএস হেগডে

টমি পো একই জিনিস 2 বছর আগে পোস্ট করেছেন।
phil294

হাই ব্লুহির্ন, ওয়াও এটি একটি পুরানো প্রশ্ন। আমার মনে হয় খেজুরের সাথে কিছু হয়েছে। আমি প্রশ্নটি জিজ্ঞাসা করার খুব শীঘ্রই উত্তর দেওয়া স্বতন্ত্রভাবে মনে রাখি, এবং সেখানে কেবলমাত্র কয়েকটি উত্তর ছিল। প্রশ্নটি অন্য একটিতে মিশে গিয়েছিল, এসও কি তা করে?
বজার্ক ফ্রুন্ড-হ্যানসেন

হ্যাঁ আমি সঠিকভাবে মনে আছে। আমি মূলত এই প্রশ্নের উত্তর দিয়েছি stackoverflow.com/questions/14703318/… একই দিন জিজ্ঞাসা করা হয়েছিল, 2 বছর পরে এটি এটিকে একীভূত করা হয়েছিল। আমার উত্তরটি এইভাবে সরানো হলে আমাকে সদৃশ উত্তরের জন্য খুব কমই দোষ দেওয়া যায়।
বজার্ক ফ্রুন্ড-হানসেন

37
pax> echo a.b.js | sed 's/\.[^.]*$//'
a.b
pax> echo a.b.js | sed 's/^.*\.//'
js

সূক্ষ্ম কাজ করে, যাতে আপনি কেবল ব্যবহার করতে পারেন:

pax> FILE=a.b.js
pax> NAME=$(echo "$FILE" | sed 's/\.[^.]*$//')
pax> EXTENSION=$(echo "$FILE" | sed 's/^.*\.//')
pax> echo $NAME
a.b
pax> echo $EXTENSION
js

কমান্ডগুলি, উপায় দ্বারা, নিম্নলিখিত হিসাবে কাজ করে।

কমান্ডটি অক্ষরের NAMEপরিবর্তে লাইনের শেষ অবধি "."অনেকগুলি অক্ষর অক্ষরকে প্রতিস্থাপন করে ".", কিছুই না দিয়ে (অর্থাত্, এটি চূড়ান্ত থেকে লাইনটির শেষ অবধি সমস্ত কিছু সরিয়ে দেয় ".") inc এটি মূলত রেজেেক্স ট্র্যাকারি ব্যবহার করে একটি লোভহীন প্রতিস্থাপন।

রেখার শুরুতে EXTENSIONএকটি "."অক্ষর অনুসারে কয়েকটি সংখ্যক অক্ষরের পরিবর্তে কমান্ডের কিছু নেই (অর্থাত্, এটি লাইনের শুরু থেকে চূড়ান্ত বিন্দু, সমেত সমস্ত কিছু সরিয়ে দেয়)। এটি একটি লোভী বিকল্প যা ডিফল্ট ক্রিয়া।


ফাইল এবং এক্সটেনশন ছাড়াই এই বিরতি হ'ল এটি নাম এবং প্রসারণের জন্য একই মুদ্রণ করবে। সুতরাং আমি sed 's,\.[^\.]*$,,'নাম এবং sed 's,.*\.,., ;t ;g'এক্সটেনশনের জন্য ব্যবহার করি ( সাধারণত কমান্ডের সাথে atypical testএবং getকমান্ড ব্যবহার করে substitute)।
hIpPy

32

মেলেন একটি ব্লগ পোস্টে একটি মন্তব্যে লিখেছেন:

ব্যাশ ব্যবহার করে, ${file%.*}এক্সটেনশন ছাড়াই ফাইলের নাম ${file##*.}পাওয়া এবং একা এক্সটেনশান পেতে there's এটাই,

file="thisfile.txt"
echo "filename: ${file%.*}"
echo "extension: ${file##*.}"

আউটপুট:

filename: thisfile
extension: txt


29

কোন প্রয়োজন সঙ্গে বিরক্ত করার জন্য awkবা sedবা এমনকি perlএই সহজ কাজের জন্য। একটি খাঁটি-বাশ, - os.path.splitext()সামঞ্জস্যপূর্ণ সমাধান রয়েছে যা কেবলমাত্র প্যারামিটার বিস্তৃতি ব্যবহার করে।

রেফারেন্স বাস্তবায়ন

এর ডকুমেন্টেশন os.path.splitext(path):

একজোড়া মধ্যে পথনাম পথ বিভক্ত (root, ext)যেমন যে root + ext == path, এবং EXT খালি থাকে বা একটি নির্দিষ্ট সময়ের দিয়ে শুরু হয় এবং সবচেয়ে এক সময়ে ধারণ করে। বেসনামের শীর্ষস্থানীয় পিরিয়ডগুলি উপেক্ষা করা হয়; splitext('.cshrc')আয় ('.cshrc', '')

পাইথন কোড:

root, ext = os.path.splitext(path)

বাশ বাস্তবায়ন

নেতৃস্থানীয় সময়কাল সম্মান

root="${path%.*}"
ext="${path#"$root"}"

নেতৃস্থানীয় পিরিয়ড উপেক্ষা করা

root="${path#.}";root="${path%"$root"}${root%.*}"
ext="${path#"$root"}"

টেস্ট

অগ্রণী পর্যায়ক্রমিক প্রয়োগগুলি উপেক্ষা করার জন্য এখানে পরীক্ষার কেসগুলি রয়েছে , যা প্রতিটি ইনপুটটিতে পাইথন রেফারেন্স প্রয়োগের সাথে মেলে।

|---------------|-----------|-------|
|path           |root       |ext    |
|---------------|-----------|-------|
|' .txt'        |' '        |'.txt' |
|' .txt.txt'    |' .txt'    |'.txt' |
|' txt'         |' txt'     |''     |
|'*.txt.txt'    |'*.txt'    |'.txt' |
|'.cshrc'       |'.cshrc'   |''     |
|'.txt'         |'.txt'     |''     |
|'?.txt.txt'    |'?.txt'    |'.txt' |
|'\n.txt.txt'   |'\n.txt'   |'.txt' |
|'\t.txt.txt'   |'\t.txt'   |'.txt' |
|'a b.txt.txt'  |'a b.txt'  |'.txt' |
|'a*b.txt.txt'  |'a*b.txt'  |'.txt' |
|'a?b.txt.txt'  |'a?b.txt'  |'.txt' |
|'a\nb.txt.txt' |'a\nb.txt' |'.txt' |
|'a\tb.txt.txt' |'a\tb.txt' |'.txt' |
|'txt'          |'txt'      |''     |
|'txt.pdf'      |'txt'      |'.pdf' |
|'txt.tar.gz'   |'txt.tar'  |'.gz'  |
|'txt.txt'      |'txt'      |'.txt' |
|---------------|-----------|-------|

পরীক্ষার ফলাফল

সমস্ত পরীক্ষা পাস।


2
না, এর বেস ফাইলের নামটি এবং এক্সটেনশন হওয়া text.tar.gzউচিতtext.tar.gz
ফ্রেডেরিক99

2
@ ফ্রেডরিক 99 যেমন আমি বলেছি সমাধানটি os.path.splitextপাইথনের প্রয়োগের সাথে মেলে । সম্ভাব্য বিতর্কিত ইনপুটগুলির জন্য সেই বাস্তবায়ন বুদ্ধিমান কিনা।
সাইকেল

( "$root") প্যাটার্নের মধ্যে উদ্ধৃতিগুলি কীভাবে কাজ করবে? এগুলি বাদ দিলে কী ঘটতে পারে? (আমি এই বিষয়ে কোনও ডকুমেন্টেশন খুঁজে পাইনি Also) এছাড়াও কীভাবে এই হ্যান্ডেল ফাইলের নামগুলি *বা ?তাদের মধ্যে রয়েছে?
ymett

ঠিক আছে, আমাকে পরীক্ষা অনুষ্ঠান কোট প্যাটার্ন একটি আক্ষরিক অর্থাত করতে, *এবং ?বিশেষ হয় না। সুতরাং আমার প্রশ্নের দুটি অংশ একে অপরের উত্তর। আমি কি ঠিক করছি যে এটি নথিভুক্ত নয়? অথবা এটুকু থেকে বোঝা যায় যে কোটগুলি সাধারণভাবে গ্লোব সম্প্রসারণকে অক্ষম করে?
ymett

জমকালো উত্তর! রুটটি গণনার জন্য আমি কিছুটা সহজ বৈকল্পিকের পরামর্শ দেব: root="${path#?}";root="${path::1}${root%.*}"- তারপরে এক্সটেনশানটি বের করার জন্য একই ধরণের এগিয়ে যান।
মাওলান

26

আপনি cutশেষ দুটি এক্সটেনশন ( ".tar.gz"অংশ) সরাতে কমান্ডটি ব্যবহার করতে পারেন :

$ echo "foo.tar.gz" | cut -d'.' --complement -f2-
foo

যেমনটি একটি মন্তব্যে ক্লেটন হিউজেস দ্বারা উল্লিখিত হয়েছে, এটি প্রশ্নের প্রকৃত উদাহরণের জন্য কাজ করবে না। সুতরাং বিকল্প হিসাবে আমি sedবর্ধিত নিয়মিত এক্সপ্রেশনগুলির সাথে এটি ব্যবহার করার প্রস্তাব করছি :

$ echo "mpc-1.0.1.tar.gz" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'
mpc-1.0.1

এটি শর্তহীনভাবে শেষ দুটি (আলফা-সংখ্যাসূচক) এক্সটেনশনগুলি সরিয়ে কাজ করে।

[অ্যান্ডারস লিন্ডাহলের মন্তব্য শেষে আবার আপডেট হয়েছে]


4
এটি কেবলমাত্র সেই ক্ষেত্রে কাজ করে যেখানে ফাইলের নাম / পাথে অন্য কোনও বিন্দু থাকে না: প্রতিধ্বনি "mpc-1.0.1.tar.gz" | কাটা-ডি '। - কমপ্লেমেন্ট -f2- "এমপিসি -1" উত্পাদন করে (সীমিত করার পরে প্রথম প্রথম দুটি ক্ষেত্র।)
ক্লেটন হিউজেস

@ ক্লেটন হিউজেস আপনি সঠিক, এবং আমার এটি আরও ভাল করে পরীক্ষা করা উচিত ছিল। আরও একটি সমাধান যুক্ত করা হয়েছে।
কিছু প্রোগ্রামার

সিড এক্সপ্রেশন $ফাইলের নামের শেষে ম্যাচ করা এক্সটেনশানটি আছে কিনা তা পরীক্ষা করতে ব্যবহার করা উচিত । অন্যথায়, মত একটি ফাইলের নাম i.like.tar.gz.files.tar.bz2অপ্রত্যাশিত ফলাফল হতে পারে।
অ্যান্ডার্স লিন্ডাল

@ এন্ডারস লিন্ডাহল এটি এখনও বাড়বে, যদি এক্সটেনশনের ক্রমটি sedচেইন ক্রমের বিপরীত হয় । এমনকি $শেষে একটি ফাইলের নাম যেমন mpc-1.0.1.tar.bz2.tar.gzউভয় .tar.gzএবং তারপরে মুছে ফেলা হবে .tar.bz2
কিছু প্রোগ্রামার

$ প্রতিধ্বনি "foo.tar.gz" | কাটা-ডি '। -f2- ছাড়া - কমপ্লিমেন্ট স্ট্রিংয়ের শেষে দ্বিতীয় বিভক্ত আইটেমটি পাবেন $ প্রতিধ্বনি "foo.tar.gz" | কাটা-ডি '। -f2- tar.gz
জিন ব্ল্যাক

23

awkসফটওয়্যার প্যাকেজগুলির জন্য সংস্করণ নম্বরগুলি বের করার মতো কয়েকটি উন্নত ব্যবহারের ক্ষেত্রে সহ কিছু বিকল্প পরামর্শ (বেশিরভাগ ক্ষেত্রে ) এখানে ।

f='/path/to/complex/file.1.0.1.tar.gz'

# Filename : 'file.1.0.x.tar.gz'
    echo "$f" | awk -F'/' '{print $NF}'

# Extension (last): 'gz'
    echo "$f" | awk -F'[.]' '{print $NF}'

# Extension (all) : '1.0.1.tar.gz'
    echo "$f" | awk '{sub(/[^.]*[.]/, "", $0)} 1'

# Extension (last-2): 'tar.gz'
    echo "$f" | awk -F'[.]' '{print $(NF-1)"."$NF}'

# Basename : 'file'
    echo "$f" | awk '{gsub(/.*[/]|[.].*/, "", $0)} 1'

# Basename-extended : 'file.1.0.1.tar'
    echo "$f" | awk '{gsub(/.*[/]|[.]{1}[^.]+$/, "", $0)} 1'

# Path : '/path/to/complex/'
    echo "$f" | awk '{match($0, /.*[/]/, a); print a[0]}'
    # or 
    echo "$f" | grep -Eo '.*[/]'

# Folder (containing the file) : 'complex'
    echo "$f" | awk -F'/' '{$1=""; print $(NF-1)}'

# Version : '1.0.1'
    # Defined as 'number.number' or 'number.number.number'
    echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?'

    # Version - major : '1'
    echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f1

    # Version - minor : '0'
    echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f2

    # Version - patch : '1'
    echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f3

# All Components : "path to complex file 1 0 1 tar gz"
    echo "$f" | awk -F'[/.]' '{$1=""; print $0}'

# Is absolute : True (exit-code : 0)
    # Return true if it is an absolute path (starting with '/' or '~/'
    echo "$f" | grep -q '^[/]\|^~/'

সমস্ত ব্যবহারের ক্ষেত্রে মধ্যবর্তী ফলাফলের উপর নির্ভর না করে মূল পুরো পথটি ইনপুট হিসাবে ব্যবহার করা হচ্ছে।


20

গৃহীত উত্তর ভাল কাজ করে টিপিক্যাল ক্ষেত্রে কিন্তু ব্যর্থ প্রান্ত মামলা , যথা:

  • এক্সটেনশন ছাড়াই ফাইলনামের জন্য ( এই উত্তরের অবশিষ্টাংশে প্রত্যয় নামে পরিচিত ) extension=${filename##*.}খালি স্ট্রিংয়ের পরিবর্তে ইনপুট ফাইলের নাম দেয়।
  • extension=${filename##*.}প্রাথমিকটি .কনভেনশনের বিপরীতে অন্তর্ভুক্ত করে না ।
    • অন্ধভাবে প্রিপেন্ডিং .প্রত্যয় ছাড়াই ফাইল নামের জন্য কাজ করবে না।
  • filename="${filename%.*}"কনফিগারেশনের বিপরীতে যদি ইনপুট ফাইলের নামটি শুরু হয় .এবং এর সাথে কোনও .অক্ষর (যেমন, .bash_profile) না থাকে তবে খালি স্ট্রিংটি হবে ।

---------

সুতরাং, সমস্ত প্রান্তের কেসগুলি কভার করে এমন দৃ a ় সমাধানের জটিলতা একটি ফাংশনটির জন্য কল করে - নীচে এর সংজ্ঞাটি দেখুন; এটি কোনও পথের সমস্ত উপাদান ফিরে আসতে পারে

উদাহরণ কল:

splitPath '/etc/bash.bashrc' dir fname fnameroot suffix
# -> $dir == '/etc'
# -> $fname == 'bash.bashrc'
# -> $fnameroot == 'bash'
# -> $suffix == '.bashrc'

নোট করুন যে ইনপুট পাথের পরে যুক্তিগুলি অবাধে চয়ন করা হয়েছে, অবস্থানগত ভেরিয়েবলের নাম
ভেরিয়েবলগুলি এড়িয়ে যাওয়ার জন্য যেগুলি আগ্রহী সেগুলির আগে নয়, নির্দিষ্ট করুন _(থ্রো-অ্যাওর ভেরিয়েবল ব্যবহার করার জন্য $_) বা ''; উদাহরণস্বরূপ, কেবলমাত্র ফাইলনামের মূল এবং এক্সটেনশানটি এক্সট্রাক্ট করতে, ব্যবহার করুন splitPath '/etc/bash.bashrc' _ _ fnameroot extension


# SYNOPSIS
#   splitPath path varDirname [varBasename [varBasenameRoot [varSuffix]]] 
# DESCRIPTION
#   Splits the specified input path into its components and returns them by assigning
#   them to variables with the specified *names*.
#   Specify '' or throw-away variable _ to skip earlier variables, if necessary.
#   The filename suffix, if any, always starts with '.' - only the *last*
#   '.'-prefixed token is reported as the suffix.
#   As with `dirname`, varDirname will report '.' (current dir) for input paths
#   that are mere filenames, and '/' for the root dir.
#   As with `dirname` and `basename`, a trailing '/' in the input path is ignored.
#   A '.' as the very first char. of a filename is NOT considered the beginning
#   of a filename suffix.
# EXAMPLE
#   splitPath '/home/jdoe/readme.txt' parentpath fname fnameroot suffix
#   echo "$parentpath" # -> '/home/jdoe'
#   echo "$fname" # -> 'readme.txt'
#   echo "$fnameroot" # -> 'readme'
#   echo "$suffix" # -> '.txt'
#   ---
#   splitPath '/home/jdoe/readme.txt' _ _ fnameroot
#   echo "$fnameroot" # -> 'readme'  
splitPath() {
  local _sp_dirname= _sp_basename= _sp_basename_root= _sp_suffix=
    # simple argument validation
  (( $# >= 2 )) || { echo "$FUNCNAME: ERROR: Specify an input path and at least 1 output variable name." >&2; exit 2; }
    # extract dirname (parent path) and basename (filename)
  _sp_dirname=$(dirname "$1")
  _sp_basename=$(basename "$1")
    # determine suffix, if any
  _sp_suffix=$([[ $_sp_basename = *.* ]] && printf %s ".${_sp_basename##*.}" || printf '')
    # determine basename root (filemane w/o suffix)
  if [[ "$_sp_basename" == "$_sp_suffix" ]]; then # does filename start with '.'?
      _sp_basename_root=$_sp_basename
      _sp_suffix=''
  else # strip suffix from filename
    _sp_basename_root=${_sp_basename%$_sp_suffix}
  fi
  # assign to output vars.
  [[ -n $2 ]] && printf -v "$2" "$_sp_dirname"
  [[ -n $3 ]] && printf -v "$3" "$_sp_basename"
  [[ -n $4 ]] && printf -v "$4" "$_sp_basename_root"
  [[ -n $5 ]] && printf -v "$5" "$_sp_suffix"
  return 0
}

test_paths=(
  '/etc/bash.bashrc'
  '/usr/bin/grep'
  '/Users/jdoe/.bash_profile'
  '/Library/Application Support/'
  'readme.new.txt'
)

for p in "${test_paths[@]}"; do
  echo ----- "$p"
  parentpath= fname= fnameroot= suffix=
  splitPath "$p" parentpath fname fnameroot suffix
  for n in parentpath fname fnameroot suffix; do
    echo "$n=${!n}"
  done
done

ফাংশনটি ব্যবহার করে এমন টেস্ট কোড:

test_paths=(
  '/etc/bash.bashrc'
  '/usr/bin/grep'
  '/Users/jdoe/.bash_profile'
  '/Library/Application Support/'
  'readme.new.txt'
)

for p in "${test_paths[@]}"; do
  echo ----- "$p"
  parentpath= fname= fnameroot= suffix=
  splitPath "$p" parentpath fname fnameroot suffix
  for n in parentpath fname fnameroot suffix; do
    echo "$n=${!n}"
  done
done

প্রত্যাশিত আউটপুট - প্রান্তের কেসগুলি নোট করুন:

  • একটি ফাইল নাম যার প্রত্যয় নেই
  • একটি ফাইলের নাম দিয়ে শুরু হবে .( প্রত্যয়টির শুরু হিসাবে বিবেচনা করা হবে না )
  • শেষ হওয়া একটি ইনপুট পাথ /(পিছনে /অগ্রাহ্য করা হবে)
  • একটি ইনপুট পাথ যা কেবলমাত্র একটি ফাইলের নাম ( .প্যারেন্ট পাথ হিসাবে ফিরে আসে)
  • একটি ফাইলের নাম যা .প্রিফিক্সড টোকেনের চেয়ে বেশি (কেবলমাত্র শেষেরটি প্রত্যয় হিসাবে বিবেচিত হবে):
----- /etc/bash.bashrc
parentpath=/etc
fname=bash.bashrc
fnameroot=bash
suffix=.bashrc
----- /usr/bin/grep
parentpath=/usr/bin
fname=grep
fnameroot=grep
suffix=
----- /Users/jdoe/.bash_profile
parentpath=/Users/jdoe
fname=.bash_profile
fnameroot=.bash_profile
suffix=
----- /Library/Application Support/
parentpath=/Library
fname=Application Support
fnameroot=Application Support
suffix=
----- readme.new.txt
parentpath=.
fname=readme.new.txt
fnameroot=readme.new
suffix=.txt

19

সবচেয়ে ছোট এবং সহজ সমাধান (একক লাইনে) হ'ল:

$ file=/blaabla/bla/blah/foo.txt
echo $(basename ${file%.*}) # foo

এটি একটি অকেজো ব্যবহারecho । ফলস্বরূপ ফলাফল প্রদর্শন করার আগে থেকেই আউটপুটটিতে শ্বেতক্ষেত্রের টোকেনাইজেশন এবং ওয়াইল্ডকার্ড সম্প্রসারণের জন্য বিশেষভাবে শেলটির প্রয়োজন না হলে সাধারণভাবে echo $(command)আরও ভালভাবে লেখা হয় । কুইজ: এর আউটপুট কী (এবং যদি আপনি সত্যই এটি চান তবে আপনি সত্যিই ন্যায়সঙ্গত চান )। commandcommandecho $(echo '*')echo *
ট্রিপলি

@ ট্রিপলি আমি echoকমান্ডটি একেবারেই ব্যবহার করিনি । আমি এটি ব্যবহার করার জন্য ফলাফলটি fooদ্বিতীয় লাইনের ফলস্বরূপ 3 য় লাইনে প্রদর্শিত হচ্ছে তা প্রদর্শন করতে ব্যবহার করেছি ।
রন

তবে ঠিক basename "${file%.*}"একই কাজ করবে; আপনি তার আউটপুট ক্যাপচার করতে একটি কমান্ড বিকল্প ব্যবহার করছেন, কেবলমাত্র echoসেই একই আউটপুটটিতে তাত্ক্ষণিক। (মূল্য উদ্ধৃতি ছাড়া, ফলাফলের নামমাত্র আলাদা হয়; কিন্তু যে একটি বৈশিষ্ট্য কমই প্রাসঙ্গিক, অনেক কম, এখানে।)
tripleee

এছাড়াও basename "$file" .txtপ্যারামিটার প্রতিকল্পন জটিলতা এড়াতে।
ট্রিপলি

1
@ রন তাকে আমাদের সময় নষ্ট করার অভিযোগ করার আগে তার প্রথম মন্তব্যটি পড়ুন।
ফ্রেডেরিক99

14

আমি মনে করি আপনার যদি কেবল ফাইলটির নাম প্রয়োজন হয় তবে আপনি এটি চেষ্টা করতে পারেন:

FULLPATH=/usr/share/X11/xorg.conf.d/50-synaptics.conf

# Remove all the prefix until the "/" character
FILENAME=${FULLPATH##*/}

# Remove all the prefix until the "." character
FILEEXTENSION=${FILENAME##*.}

# Remove a suffix, in our case, the filename. This will return the name of the directory that contains this file.
BASEDIRECTORY=${FULLPATH%$FILENAME}

echo "path = $FULLPATH"
echo "file name = $FILENAME"
echo "file extension = $FILEEXTENSION"
echo "base directory = $BASEDIRECTORY"

এবং এটি সব = ডি।


সবেমাত্র বেসডিরেক্টরি চেয়েছিলেন :) ধন্যবাদ!
কার্লোস রিকার্ডো

12

আপনি সমস্ত ক্ষেত্র এবং পরবর্তী -ক্ষেত্রের নম্বরটিতে যুক্ত করার জন্য কাটকে বাধ্য করতে পারেন ।

NAME=`basename "$FILE"`
EXTENSION=`echo "$NAME" | cut -d'.' -f2-`

সুতরাং যদি ফাইল হয় eth0.pcap.gz তবে এক্সটেনশান হবেpcap.gz

একই যুক্তি ব্যবহার করে, আপনি নিম্নরূপে কাট দিয়ে '-' ব্যবহার করে ফাইলের নামও আনতে পারেন:

NAME=`basename "$FILE" | cut -d'.' -f-1`

এটি এমন কোনও ফাইল নামগুলির জন্যও কাজ করে যাগুলির কোনও এক্সটেনশন নেই।


8

যাদু ফাইল স্বীকৃতি

এই স্ট্যাক ওভারফ্লো প্রশ্নটিতে প্রচুর ভাল উত্তর ছাড়াও আমি যুক্ত করতে চাই:

লিনাক্স এবং অন্যান্য ইউনিক্সের অধীনে একটি ম্যাজিক কমান্ড রয়েছে fileযা ফাইলের প্রথম বাইট বিশ্লেষণ করে ফাইল টাইপ সনাক্ত করে do এটি একটি খুব পুরানো সরঞ্জাম, প্রিন্ট সার্ভারের জন্য আদ্যক্ষর ব্যবহৃত (যদি এর জন্য তৈরি না হয় ... তবে আমি সে সম্পর্কে নিশ্চিত নই)।

file myfile.txt
myfile.txt: UTF-8 Unicode text

file -b --mime-type myfile.txt
text/plain

স্ট্যান্ডার্ড এক্সটেনশানগুলি পাওয়া যাবে /etc/mime.types(আমার ডেবিয়ান জিএনইউ / লিনাক্স ডেস্কটপে। দেখুন man fileএবং man mime.typesসম্ভবত আপনাকে fileইউটিলিটি এবং mime-supportপ্যাকেজ ইনস্টল করতে হবে ):

grep $( file -b --mime-type myfile.txt ) </etc/mime.types
text/plain      asc txt text pot brf srt

আপনি একটি তৈরি করতে পারে ডান এক্সটেনশন নির্ধারণের জন্য ফাংশন। এখানে সামান্য (নিখুঁত নয়) নমুনা রয়েছে:

file2ext() {
    local _mimetype=$(file -Lb --mime-type "$1") _line _basemimetype
    case ${_mimetype##*[/.-]} in
        gzip | bzip2 | xz | z )
            _mimetype=${_mimetype##*[/.-]}
            _mimetype=${_mimetype//ip}
            _basemimetype=$(file -zLb --mime-type "$1")
            ;;
        stream )
            _mimetype=($(file -Lb "$1"))
            [ "${_mimetype[1]}" = "compressed" ] &&
                _basemimetype=$(file -b --mime-type - < <(
                        ${_mimetype,,} -d <"$1")) ||
                _basemimetype=${_mimetype,,}
            _mimetype=${_mimetype,,}
            ;;
        executable )  _mimetype='' _basemimetype='' ;;
        dosexec )     _mimetype='' _basemimetype='exe' ;;
        shellscript ) _mimetype='' _basemimetype='sh' ;;
        * )
            _basemimetype=$_mimetype
            _mimetype=''
            ;;
    esac
    while read -a _line ;do
        if [ "$_line" == "$_basemimetype" ] ;then
            [ "$_line[1]" ] &&
                _basemimetype=${_line[1]} ||
                _basemimetype=${_basemimetype##*[/.-]}
            break
        fi
        done </etc/mime.types
    case ${_basemimetype##*[/.-]} in
        executable ) _basemimetype='' ;;
        shellscript ) _basemimetype='sh' ;;
        dosexec ) _basemimetype='exe' ;;
        * ) ;;
    esac
    [ "$_mimetype" ] && [ "$_basemimetype" != "$_mimetype" ] &&
      printf ${2+-v} $2 "%s.%s" ${_basemimetype##*[/.-]} ${_mimetype##*[/.-]} ||
      printf ${2+-v} $2 "%s" ${_basemimetype##*[/.-]}
}

এই ফাংশনটি ব্যাশ ভেরিয়েবল সেট করতে পারে যা পরে ব্যবহার করা যেতে পারে:

(এটি @ পেটেশের সঠিক উত্তর থেকে অনুপ্রাণিত):

filename=$(basename "$fullfile")
filename="${filename%.*}"
file2ext "$fullfile" extension

echo "$fullfile -> $filename . $extension"

8

ঠিক আছে তাই যদি আমি সঠিকভাবে বুঝতে পারি তবে এখানে সমস্যাটি হ'ল একাধিক এক্সটেনশন রয়েছে এমন কোনও ফাইলের নাম এবং সম্পূর্ণ এক্সটেনশন কীভাবে পাবেন stuff.tar.gz

এটি আমার পক্ষে কাজ করে:

fullfile="stuff.tar.gz"
fileExt=${fullfile#*.}
fileName=${fullfile%*.$fileExt}

এটি আপনাকে stuffফাইলের নাম এবং .tar.gzএক্সটেনশন হিসাবে দেবে। এটি 0 সহ যে কোনও সংখ্যক এক্সটেনশনের জন্য কাজ করে Hope আশা করি এটি একই সমস্যাযুক্ত যে কোনও ব্যক্তির জন্য সহায়তা করে =)


সঠিক ফলাফল (সেই অনুযায়ী os.path.splitext, যা ওপি চায়) তা ('stuff.tar', '.gz')
সাইকেলটি

6

আমি নিম্নলিখিত স্ক্রিপ্ট ব্যবহার

$ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev
foo

এটি মোটেই দক্ষ নয়। অনেকবার কাঁটাচামচ করা যা একেবারেই অপ্রয়োজনীয় কারণ এই বাহ্যিক কোনও বাহ্যিক আদেশ এবং কাঁটাচামচ না করে খাঁটি বাশে সঞ্চালন করা যেতে পারে।
কোডফোরস্টার

5
$ F = "text file.test.txt"  
$ echo ${F/*./}  
txt  

এটি ফাইলের একাধিক বিন্দু এবং শূন্যস্থান পূরণ করে, তবে যদি কোনও এক্সটেনশন না থাকে তবে এটি ফাইলের নামটি নিজেই ফিরিয়ে দেয়। যদিও চেক করা সহজ; কেবল ফাইলের নাম এবং এক্সটেনশান একই হওয়ার জন্য পরীক্ষা করুন।

স্বাভাবিকভাবেই এই পদ্ধতিটি .tar.gz ফাইলগুলির জন্য কাজ করে না। তবে এটি একটি দুই ধাপের প্রক্রিয়াতে পরিচালনা করা যেতে পারে। যদি এক্সটেনশনটি জিজেড হয় তবে তার সাথে আবারও টর এক্সটেনশন রয়েছে কিনা তা পরীক্ষা করে দেখুন।


5

মাছের মধ্যে ফাইলের নাম এবং এক্সটেনশন কীভাবে নিষ্কাশন করবেন :

function split-filename-extension --description "Prints the filename and extension"
  for file in $argv
    if test -f $file
      set --local extension (echo $file | awk -F. '{print $NF}')
      set --local filename (basename $file .$extension)
      echo "$filename $extension"
    else
      echo "$file is not a valid file"
    end
  end
end

ক্যাভেটস: সর্বশেষ বিন্দুতে বিভক্ত হয়, যা সেগুলির মধ্যে বিন্দু সহ ফাইলের নামগুলির জন্য ভাল কাজ করে তবে সেগুলিতে বিন্দুর সাহায্যে এক্সটেনশনের পক্ষে ভাল হয় না। নীচে উদাহরণ দেখুন।

ব্যবহার:

$ split-filename-extension foo-0.4.2.zip bar.tar.gz
foo-0.4.2 zip  # Looks good!
bar.tar gz  # Careful, you probably want .tar.gz as the extension.

এটি করার আরও ভাল উপায় আছে। আমার উত্তরটি উন্নত করতে নির্দ্বিধায় দ্বিধা করুন।


যদি এক্সটেনশনের একটি সীমিত সেট থাকে যার সাথে আপনি আচরণ করছেন এবং আপনি সেগুলি সব জানেন তবে এটি ব্যবহার করে দেখুন:

switch $file
  case *.tar
    echo (basename $file .tar) tar
  case *.tar.bz2
    echo (basename $file .tar.bz2) tar.bz2
  case *.tar.gz
    echo (basename $file .tar.gz) tar.gz
  # and so on
end

এই আছে না প্রথম উদাহরণ হিসাবে সতর্কীকরণ আছে, কিন্তু আপনি প্রতিটি ক্ষেত্রে পরিচালনা করতে তাই এটি কত এক্সটেনশন আশা করতে পারেন উপর নির্ভর করে আরো ক্লান্তিকর হতে পারে আছে।


4

এখানে কোড awk । এটি আরও সহজভাবে করা যেতে পারে। তবে আমি এডব্লিউকে তেমন ভাল নই।

filename$ ls
abc.a.txt  a.b.c.txt  pp-kk.txt
filename$ find . -type f | awk -F/ '{print $2}' | rev | awk -F"." '{$1="";print}' | rev | awk 'gsub(" ",".") ,sub(".$", "")'
abc.a
a.b.c
pp-kk
filename$ find . -type f | awk -F/ '{print $2}' | awk -F"." '{print $NF}'
txt
txt
txt

আপনার শেষ উদাহরণে প্রথম বিশ্রী বিবৃতি প্রয়োজন হবে না, তাই না?
বিএইচএসপিটমনকি

আপনি অন্য কিছু করে Awk থেকে Awk এর পাইপিং এড়াতে পারবেন split()awk -F / '{ n=split($2, a, "."); print a[n] }' uses / the শীর্ষ স্তরের ডিলিমিটার হিসাবে তবে দ্বিতীয় ক্ষেত্রটি বিভক্ত .করে নতুন অ্যারে থেকে শেষ উপাদানটি মুদ্রণ করে।
ট্রিপলি

4

সহজভাবে ব্যবহার ${parameter%word}

আপনার ক্ষেত্রে:

${FILE%.*}

আপনি যদি এটি পরীক্ষা করতে চান তবে নিম্নলিখিত সমস্ত কাজ করে এবং কেবল এক্সটেনশনটি সরিয়ে ফেলুন:

FILE=abc.xyz; echo ${FILE%.*};
FILE=123.abc.xyz; echo ${FILE%.*};
FILE=abc; echo ${FILE%.*};

2
ডাউনটা কেন? এটি এখনও কার্যকর, যদিও =লক্ষণগুলির চারপাশে ফাঁকা স্থান থাকা উচিত নয় ।
সিলভার ওল্ফ - মনিকা

1
এটি কাজ করে। ধন্যবাদ! (এখন এটির সমান চিহ্নগুলির চারপাশে ফাঁকা স্থান নেই, যদি সে কারণেই এটি হ্রাস করা হত)
অ্যালেক্স। এস।

3

পেটেশ উত্তর থেকে বিল্ডিং , যদি কেবল ফাইলের নাম প্রয়োজন হয় তবে পথ এবং এক্সটেনশন উভয়ই একক লাইনে ছড়িয়ে যেতে পারে,

filename=$(basename ${fullname%.*})

আমার পক্ষে কাজ করেনি: "বেসনাম: অনুপস্থিত অপরেন্ড আরও তথ্যের জন্য 'বেসনাম - হেল্প' চেষ্টা করুন" "
হেলমি

আজব, আপনি কি বাশ ব্যবহার করছেন তা নিশ্চিত? আমার ক্ষেত্রে, উভয় সংস্করণ 3.2.25 (পুরাতন CentOS) এবং 4.3.30 (দেবিয়ান জেসি) এর সাথে এটি নির্দোষভাবে কাজ করে।
সিভিআর

ফাইলনামে হয়ত জায়গা আছে? ব্যবহার করার চেষ্টা করুনfilename="$(basename "${fullname%.*}")"
অ্যাড্রিয়ান

দ্বিতীয় আর্গুমেন্টটি basenameisচ্ছিক, তবে ফেলা বন্ধ করার জন্য এক্সটেনশনটি নির্দিষ্ট করে। প্রতিস্থাপনটি এখনও কার্যকর হতে পারে তবে সম্ভবত basenameবাস্তবে তা নয়, যেহেতু আপনি শেল বিল্টিনসের সাহায্যে বাস্তবে এই সমস্ত প্রতিস্থাপন করতে পারেন।
ট্রিপলি

3

@ এমকিলেটমেন্টের দুর্দান্ত, এবং এলোমেলো, দরকারী বাশিমাসমূহ - পাশাপাশি এই / অন্যান্য প্রশ্নের উত্তর / "যেটি ইন্টারনেটকে ঘৃণা করে" - এর সম্পূর্ণ ভিত্তিতে আমি এগুলি সমস্ত কিছুটা গুটিয়ে রেখেছি , কিছুটা আরও বোধগম্য, আমার (বা আপনার) জন্য পুনরায় ব্যবহারযোগ্য ফাংশন.bash_profile যা (আমি বিবেচনা করি) আপনার dirname/ basename/ এর কী আরও বেশি শক্তিশালী সংস্করণ হওয়া উচিত সেদিকে খেয়াল রাখে ..

function path { SAVEIFS=$IFS; IFS=""   # stash IFS for safe-keeping, etc.
    [[ $# != 2 ]] && echo "usage: path <path> <dir|name|fullname|ext>" && return    # demand 2 arguments
    [[ $1 =~ ^(.*/)?(.+)?$ ]] && {     # regex parse the path
        dir=${BASH_REMATCH[1]}
        file=${BASH_REMATCH[2]}
        ext=$([[ $file = *.* ]] && printf %s ${file##*.} || printf '')
        # edge cases for extensionless files and files like ".nesh_profile.coffee"
        [[ $file == $ext ]] && fnr=$file && ext='' || fnr=${file:0:$((${#file}-${#ext}))}
        case "$2" in
             dir) echo      "${dir%/*}"; ;;
            name) echo      "${fnr%.*}"; ;;
        fullname) echo "${fnr%.*}.$ext"; ;;
             ext) echo           "$ext"; ;;
        esac
    }
    IFS=$SAVEIFS
}     

ব্যবহারের উদাহরণগুলি ...

SOMEPATH=/path/to.some/.random\ file.gzip
path $SOMEPATH dir        # /path/to.some
path $SOMEPATH name       # .random file
path $SOMEPATH ext        # gzip
path $SOMEPATH fullname   # .random file.gzip                     
path gobbledygook         # usage: -bash <path> <dir|name|fullname|ext>

1
সুন্দরভাবে সম্পন্ন; কয়েকটি পরামর্শ: - আপনি মোটেই নির্ভর করছেন বলে মনে হয় না $IFS(এবং আপনি যদি localথাকতেন তবে এটি সেট করার প্রভাবটি স্থানীয়করণ করতে আপনি ব্যবহার করতে পারেন )। - localভেরিয়েবল ব্যবহার করা ভাল । - আপনার ত্রুটির বার্তা আউটপুট হওয়া উচিত stderr, না stdout(ব্যবহারের 1>&2), এবং আপনি একটি নন-জিরো প্রস্থান কোড ফেরত পাঠাবেন। - নামকরণ fullnameকরা ভাল basename(পূর্ববর্তীটি dir উপাদানগুলির সাথে একটি পথ নির্দেশ করে)। - nameনিঃশর্তভাবে একটি .(পিরিয়ড) সংযোজন করে , এমনকি আসলটি না থাকলেও। আপনি কেবল basenameইউটিলিটিটি ব্যবহার করতে পারেন তবে নোট করুন যে এটি একটি সমাপ্তি উপেক্ষা করে /
mklement0

2

একটি সহজ উত্তর:

POSIX ভেরিয়েবলের উত্তরটি প্রসারিত করতে নোট করুন যে আপনি আরও আকর্ষণীয় নিদর্শনগুলি করতে পারেন। সুতরাং এখানে বিশদ বিবরণের জন্য, আপনি কেবল এটি করতে পারেন:

tar -zxvf $1
cd ${1%.tar.*}

এটি .tar এর শেষ ঘটনাটি কেটে দেবে। <কিছু>

আরও সাধারণভাবে, যদি আপনি সর্বশেষ ঘটনাটি সরাতে চান। <কিছু><something-else> তাহলে

${1.*.*}

ভাল কাজ করা উচিত।

উপরের উত্তরটি লিঙ্কটি মারা গেছে বলে মনে হচ্ছে। এখানে স্ট্রিং ম্যানিপুলেশন আপনি সরাসরি ব্যাশ করতে পারি না TLDP থেকে একটি গুচ্ছ একটি মহান ব্যাখ্যা


ম্যাচ কেস-সংবেদনশীল করার কোনও উপায় আছে কি?
টোনিক্স

2

আপনি যদি খালি এক্সটেনশানগুলিকেও অনুমতি দিতে চান তবে এটিই আমার সাথে সংক্ষিপ্ততম হতে পারে:

echo 'hello.txt' | sed -r 's/.+\.(.+)|.*/\1/' # EXTENSION
echo 'hello.txt' | sed -r 's/(.+)\..+|(.*)/\1\2/' # FILENAME

1 ম লাইনটি ব্যাখ্যা করেছে: এটি PATH.EXT বা অন্য কোনওটির সাথে মেলে এবং এটিকে EXT এর সাথে প্রতিস্থাপন করে। যদি কিছু মিলে যায় তবে এক্স গ্রুপটি ধরা পড়ে না।


2

এই একমাত্র আমার জন্য কাজ করেছে:

path='folder/other_folder/file.js'

base=${path##*/}
echo ${base%.*}

>> file

এটি স্ট্রিং ইন্টারপোলেশনেও ব্যবহার করা যেতে পারে তবে দুর্ভাগ্যক্রমে আপনাকে baseআগেই সেট করতে হবে ।


1

নামগুলি কেসিংয়ের সাথে সম্পর্কিত না হলে নামগুলি অনন্য করে তুলতে আমি যখন কোনও বাশ স্ক্রিপ্ট লিখি তখন কোনও ফাইলের নাম এবং প্রসারণ সন্ধান করার জন্য আমি যে অ্যালগরিদম ব্যবহার করি তা এখানে।

#! /bin/bash 

#
# Finds 
# -- name and extension pairs
# -- null extension when there isn't an extension.
# -- Finds name of a hidden file without an extension
# 

declare -a fileNames=(
  '.Montreal' 
  '.Rome.txt' 
  'Loundon.txt' 
  'Paris' 
  'San Diego.txt'
  'San Francisco' 
  )

echo "Script ${0} finding name and extension pairs."
echo 

for theFileName in "${fileNames[@]}"
do
     echo "theFileName=${theFileName}"  

     # Get the proposed name by chopping off the extension
     name="${theFileName%.*}"

     # get extension.  Set to null when there isn't an extension
     # Thanks to mklement0 in a comment above.
     extension=$([[ "$theFileName" == *.* ]] && echo ".${theFileName##*.}" || echo '')

     # a hidden file without extenson?
     if [ "${theFileName}" = "${extension}" ] ; then
         # hidden file without extension.  Fixup.
         name=${theFileName}
         extension=""
     fi

     echo "  name=${name}"
     echo "  extension=${extension}"
done 

পরীক্ষা চালানো।

$ config/Name\&Extension.bash 
Script config/Name&Extension.bash finding name and extension pairs.

theFileName=.Montreal
  name=.Montreal
  extension=
theFileName=.Rome.txt
  name=.Rome
  extension=.txt
theFileName=Loundon.txt
  name=Loundon
  extension=.txt
theFileName=Paris
  name=Paris
  extension=
theFileName=San Diego.txt
  name=San Diego
  extension=.txt
theFileName=San Francisco
  name=San Francisco
  extension=
$ 

এফওয়াইআই: সম্পূর্ণ লিপ্যন্তরকরণ প্রোগ্রাম এবং আরও পরীক্ষার কেসগুলি এখানে পাওয়া যাবে: https://www.roidbox.com/s/4c6m0f2e28a1vxf/avoid-clashes-code.zip?dl=0


সমস্ত সমাধান থেকে এই একমাত্র এটি খালি স্ট্রিংটি ফেরত দেয় যখন ফাইলটির সাথে কোনও এক্সটেনশান নেই:extension=$([[ "$theFileName" == *.* ]] && echo ".${theFileName##*.}" || echo '')
f0nzie

1

উদাহরণস্বরূপ ফাইলটি ব্যবহার করে /Users/Jonathan/Scripts/bash/MyScript.sh, এই কোডটি:

MY_EXT=".${0##*.}"
ME=$(/usr/bin/basename "${0}" "${MY_EXT}")

${ME}সত্তা MyScript${MY_EXT}সত্তার ফলে হবে .sh:


লিপি:

#!/bin/bash
set -e

MY_EXT=".${0##*.}"
ME=$(/usr/bin/basename "${0}" "${MY_EXT}")

echo "${ME} - ${MY_EXT}"

কিছু পরীক্ষা:

$ ./MyScript.sh 
MyScript - .sh

$ bash MyScript.sh
MyScript - .sh

$ /Users/Jonathan/Scripts/bash/MyScript.sh
MyScript - .sh

$ bash /Users/Jonathan/Scripts/bash/MyScript.sh
MyScript - .sh

2
নিশ্চিত হ'ল কেন এটিতে এতগুলি ডাউন-বোট রয়েছে - এটি আসলে গৃহীত উত্তরের চেয়ে বেশি দক্ষ more (পরবর্তীকালে, এটি কোনও এক্সটেনশন ছাড়াই ইনপুট ফাইলের সাথেও ভেঙে যায় )। এর সুস্পষ্ট পথ ব্যবহার করা basenameহ'ল সম্ভবত ওভারকিল।
mklement0

1

উপরের উত্তরগুলি থেকে, পাইথনের নকল করার পক্ষে সংক্ষিপ্ততম অনিলাইনার

file, ext = os.path.splitext(path)

অনুমান করা আপনার ফাইলের আসলেই একটি এক্সটেনশন রয়েছে, তা

EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT)

আমি এই উপর ডাউনওয়েটস পেয়েছি। আমি উত্তরটি সরিয়ে দেওয়ার বিষয়ে বিবেচনা করছি, লোকেরা এটি কোনওভাবেই অপছন্দ করে।
কমনপাইক

বেসনেম এক্সটেনশন সরায় না, কেবল পথ the
ডেভিড কুলেন

ম্যান পেজটির দিকে তাকানোর পরে অনেক দিন হয়ে গেছে আমি এসইউএফএফআইএক্স বিকল্পটি ভুলে গিয়েছি।
ডেভিড কুলেন

আপনি কী এক্সটেনশনটি সরিয়ে ফেলতে চান তা জানার আগে আপনাকে কী লাগাতে হবে EXTতাই এটি পুরো পথ কচ্ছপ is (এছাড়াও, আপনার ব্যক্তিগত ভেরিয়েবল নামগুলির জন্য আপনার সমস্ত বড় হাতের এড়ানো উচিত; সেগুলি সিস্টেম ভেরিয়েবলের জন্য সংরক্ষিত))
ট্রিপল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.