কোনও ফাইলের নামে এক্সটেনশনটি ধরে নেওয়া


33

বাশ থেকে ফাইল এক্সটেনশানটি কীভাবে পাব? আমি যা চেষ্টা করেছি তা এখানে:

filename=`basename $filepath`
fileext=${filename##*.}

এটি করার মাধ্যমে আমি bz2পাথ থেকে সম্প্রসারণ পেতে পারি তবে পথটিতে /dir/subdir/file.bz2আমার সমস্যা রয়েছে /dir/subdir/file-1.0.tar.bz2

যদি সম্ভব হয় তবে আমি কেবল বাহ্যিক প্রোগ্রাম ছাড়াই ব্যাশ ব্যবহার করে সমাধানটি পছন্দ করব।

আমার প্রশ্নটি পরিষ্কার করার জন্য, আমি কেবলমাত্র একটি কমান্ড দ্বারা কোনও প্রদত্ত সংরক্ষণাগারটি বের করার জন্য একটি বাশ স্ক্রিপ্ট তৈরি করছিলাম extract path_to_file। ফাইলটি কীভাবে এক্সট্রাক্ট করা যায় তা স্ক্রিপ্ট দ্বারা তার সংক্ষেপণ বা সংরক্ষণাগার প্রকারটি দেখে নির্ধারণ করা হয়, এটি .tar.gz, .gz, .bz2 ইত্যাদি হতে পারে I আমি মনে করি এটিতে স্ট্রিং ম্যানিপুলেশন জড়িত থাকতে হবে, উদাহরণস্বরূপ যদি আমি এক্সটেনশন .gzপাই তবে আমি এর .tarআগে স্ট্রিং রয়েছে কিনা তা .gzখতিয়ে দেখা উচিত - যদি তাই হয় তবে এক্সটেনশনটি হওয়া উচিত .tar.gz


2
ফাইল = "/ Dir / subdir / ফাইল-1.0.tar.bz2"; প্রতিধ্বনি $ {ফাইল ## *।} প্রিন্ট '.bz2' এখানে। আপনি যে আউটপুটটি আশা করছেন তা কী?
axel_c

1
আমার দরকার.tar.bz2
uray

উত্তর:


19

যদি ফাইলের নাম হয় file-1.0.tar.bz2তবে এক্সটেনশনটি bz2। আপনি এক্সটেনশনটি বের করার জন্য যে পদ্ধতিটি ব্যবহার করছেন (তা fileext=${filename##*.}) পুরোপুরি বৈধ ¹

আপনি কিভাবে সিদ্ধান্ত নেন যে আপনি এক্সটেনশানটি হতে চান tar.bz2এবং bz2বা 0.tar.bz2? আপনাকে প্রথমে এই প্রশ্নের উত্তর দেওয়া দরকার। তারপরে শেল কমান্ডটি আপনার স্পেসিফিকেশনের সাথে কী মেলে তা আপনি বুঝতে পারেন।

  • একটি সম্ভাব্য স্পেসিফিকেশন হ'ল এক্সটেনশনগুলি অবশ্যই একটি চিঠি দিয়ে শুরু করা উচিত। এই হিউরিস্টিক কয়েকটি সাধারণ এক্সটেনশনের মতো ব্যর্থ হয় 7z, যা সম্ভবত বিশেষ কেস হিসাবে বিবেচিত হয়। এখানে একটি বাশ / কেএসএস / জেডএস বাস্তবায়ন:

    basename=$filename; fileext=
    while [[ $basename = ?*.* &&
             ( ${basename##*.} = [A-Za-z]* || ${basename##*.} = 7z ) ]]
    do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    fileext=${fileext%.}

    পসিক্স বহনযোগ্যতার caseজন্য, প্যাটার্ন মিলের জন্য আপনাকে একটি বিবৃতি ব্যবহার করতে হবে ।

    while case $basename in
            ?*.*) case ${basename##*.} in [A-Za-z]*|7z) true;; *) false;; esac;;
            *) false;;
          esac
    do 
  • আর একটি সম্ভাব্য স্পেসিফিকেশন হ'ল কিছু এক্সটেনশানগুলি এনকোডিংগুলি বোঝায় এবং নির্দেশ করে যে আরও স্ট্রিপিং দরকার। এখানে একটি বাশ / ksh / zsh বাস্তবায়ন (ব্যাশের shopt -s extglobঅধীনে এবং setopt ksh_globzsh এর অধীনে প্রয়োজন ):

    basename=$filename
    fileext=
    while [[ $basename = ?*.@(bz2|gz|lzma) ]]; do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    if [[ $basename = ?*.* ]]; then
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    fi
    fileext=${fileext%.}

    মনে রাখবেন এটি এটিকে 0একটি এক্সটেনশন হিসাবে বিবেচনা করে file-1.0.gz

Related এবং সম্পর্কিত কন্সট্রাক্টসগুলি পসিক্সে রয়েছে , সুতরাং এগুলি অ্যাশ, বাশ, কেএসএস বা জেডএস-এর মতো কোনও অ-অ্যান্টিক বোর্ন-স্টাইলের শেলটিতে কাজ করে। ${VARIABLE##SUFFIX}


স্ট্রিংটি শেষ হওয়ার আগে কিনা তা পরীক্ষা করে সমাধান করা উচিত . টোকেনের সংরক্ষণাগার ধরণের , উদাহরণস্বরূপ tar, যদি এটির পুনরায় সংরক্ষণের মতো 0পুনরাবৃত্তির মতো শেষ না হয়।
uray

2
@ উরে: যা এই বিশেষ ক্ষেত্রে কাজ করে তবে এটি সাধারণ সমাধান নয়। ম্যাকিয়েজের উদাহরণ.patch.lzma বিবেচনা করুন । একটি ভাল অনুসন্ধানমূলক স্ট্রিং বিবেচনা করতে হবে পরে গত .: যদি এটি একটি কম্প্রেশন প্রত্যয় এর ( .7z, .bz2, .gz, ...), stripping অবিরত।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

@ নোয়ামএম ইন্ডেন্টেশন দিয়ে কি ভুল ছিল? এটি আপনার সম্পাদনার পরে অবশ্যই স্পষ্টভাবে ভেঙে গেছে: দ্বিগুণ-নেস্টেড কোডটি একক-নেস্টেডের মতো একই রকম হয়।
গিলস 'অশুভ হওয়া বন্ধ করুন'

22

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

case "$filename" in
    *.tar.bz2) bunzip_then_untar ;;
    *.bz2)     bunzip_only ;;
    *.tar.gz)  untar_with -z ;;
    *.tgz)     untar_with -z ;;
    *.gz)      gunzip_only ;;
    *.zip)     unzip ;;
    *.7z)      do something ;;
    *)         do nothing ;;
esac

এই সমাধানটি খুব সহজ।
AsymLabs

6
$ echo "thisfile.txt"|awk -F . '{print $NF}'

এখানে মন্তব্য: http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in- Shell-script/


1
.tar.gzএক্সটেনশনের জন্য কাজ করছে না
uray

4
ওয়েল একটি .tar.gz আসলে একটি জিজিপ ফাইলের মধ্যে একটি টার হয় তাই এটি কোনও অর্থে কাজ করে যে এটি একটি জিজেপ ফাইল থেকে একটি জিজেড এক্সটেনশন সরিয়ে দেয়।
ক্রিস

2

এটিতে আমার শটটি এখানে: বিন্দুগুলিকে নিউলাইনে, পাইপের মাধ্যমে অনুবাদ করুন tail, শেষ লাইনটি পান:

$> TEXT=123.234.345.456.456.567.678
$> echo $TEXT | tr . \\n | tail -n1
678

0
echo ${filename#$(echo $filename | sed 's/\.[^[:digit:]].*$//g;')}

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

% echo $filename
2.6.35-zen2.patch.lzma
% echo ${filename#$(echo $filename | sed 's/\.[^[:digit:]].*$//g;')}
.patch.lzma

সব ক্ষেত্রে কাজ করে না। 'Foo.7z' দিয়ে চেষ্টা করুন
axel_c

printfআপনার ফাইলের -"${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
নামটিতে

@ অ্যাক্সেল_সি: ঠিক আছে, এবং আমি উদাহরণ হিসাবে ম্যাকিয়েজের মতো একই স্পেসিফিকেশনটি প্রয়োগ করেছি। "চিঠি দিয়ে শুরু করা" এর চেয়ে ভাল আপনি কী যুক্তিবাদী পরামর্শ দেন?
গিলস 'অশুভ হওয়া বন্ধ করুন'

1
@ গিলস: আমি কেবলমাত্র মনে করি আপনি ज्ञात এক্সটেনশনের প্রাক্পম্পিউটেড তালিকা ব্যবহার না করা হলে এর কোনও সমাধান নেই, কারণ একটি এক্সটেনশন যে কোনও কিছু হতে পারে।
axel_c

0

একদিন আমি এই কৌশলগুলি তৈরি করেছি:

# args: string how_many
function get_last_letters(){ echo ${1:${#1}-$2:$2}; }
function cut_last_letters(){ echo ${1:0:${#1}-$2}; }

আমি এই সোজাসুজি পদ্ধতির সন্ধান পেয়েছি, অনেক ক্ষেত্রে খুব কার্যকর, কেবল যখন এটি এক্সটেনশনের ক্ষেত্রে যায় না।

এক্সটেনশনগুলি পরীক্ষা করার জন্য - এটি সহজ এবং নির্ভরযোগ্য

~$ get_last_letters file.bz2 4
.bz2
~$ get_last_letters file.0.tar.bz2 4
.bz2

কাট-অফ এক্সটেনশনের জন্য:

~$ cut_last_letters file.0.tar.bz2 4
file.0.tar

এক্সটেনশন পরিবর্তনের জন্য:

~$ echo $(cut_last_letters file.0.tar.bz2 4).gz
file.0.tar.gz

অথবা, যদি আপনি "হ্যান্ডি ফাংশনগুলি পছন্দ করেন:

~$ function cut_last_letters_and_add(){ echo ${1:0:${#1}-$2}"$3"; }
~$ cut_last_letters_and_add file.0.tar.bz2 4 .gz
file.0.tar.gz

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


0

জ্যাকম্যান কেস-ভিত্তিক উত্তরটি বেশ ভাল এবং পোর্টেবল, তবে আপনি যদি কেবলমাত্র একটি ভেরিয়েবলের ফাইলের নাম এবং এক্সটেনশন চান তবে আমি এই সমাধানটি খুঁজে পেয়েছি:

INPUTFILE="$1"
INPUTFILEEXT=$( echo -n "$INPUTFILE" | rev | cut -d'.' -f1 | rev )
INPUTFILEEXT=$( echo -n $INPUTFILEEXT | tr '[A-Z]' '[a-z]' ) # force lowercase extension
INPUTFILENAME="`echo -n \"$INPUTFILE\" | rev | cut -d'.' -f2- | rev`"

# fix for files with multiple extensions like "gbamidi-v1.0.tar.gz"
INPUTFILEEXT2=$( echo -n "$INPUTFILENAME" | rev | cut -d'.' -f1 | rev )
if [ "$INPUTFILEEXT2" = "tar" ]; then
    # concatenate the extension
    INPUTFILEEXT="$INPUTFILEEXT2.$INPUTFILEEXT"
    # update the filename
    INPUTFILENAME="`echo -n \"$INPUTFILENAME\" | rev | cut -d'.' -f2- | rev`"
fi

এটি কেবল ডাবল এক্সটেনশনের সাথে কাজ করে এবং প্রথমটি অবশ্যই "টার" হতে হবে।

তবে আপনি স্ট্রিং দৈর্ঘ্যের পরীক্ষার সাহায্যে "টার" পরীক্ষার লাইনটি পরিবর্তন করতে পারেন এবং একাধিকবার ফিক্সটি পুনরাবৃত্তি করতে পারেন।


-1

আমি এটি ব্যবহার করে এটি সমাধান করেছি:

filename=`basename $filepath`
fileext=${filename##*.}
fileext2=${filename%.*}
fileext3=${fileext2##*.}
if [ "$fileext3" == "tar" ]; then
    fileext="tar."$fileext
fi

তবে এটি কেবল পরিচিত ক্ষেত্রে সংরক্ষণাগার প্রকারের জন্যই কাজ করে tar

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.