ব্যাশের সাথে ফাইলের নাম পরিবর্তন করা হচ্ছে


101

বাশ কীভাবে তাদের সংস্করণ নম্বরগুলি অপসারণ করতে প্যাকেজগুলির একটি সিরিজের নাম পরিবর্তন করতে পারে? আমি উভয়ের সাথে ঝাঁপিয়ে পড়েছি exprএবং %%কোনও লাভ হয়নি।

উদাহরণ:

Xft2-2.1.13.pkg হয়ে Xft2.pkg

jasper-1.900.1.pkg হয়ে jasper.pkg

xorg-libXrandr-1.2.3.pkg হয়ে xorg-libXrandr.pkg


1
আমি নিয়মিত এটি ব্যবহার করার ইচ্ছা করি, লেখার জন্য একবার ব্যবহার-প্রচুর স্ক্রিপ্ট হিসাবে। আমি যে যে সিস্টেমটি ব্যবহার করব তা এর উপর চাপ ফেলবে, তাই আমি যে ব্যাশিজমগুলি খুব সহজ of
জেরেমি এল

আরো সাধারণভাবে দেখতে stackoverflow.com/questions/28725333/...
tripleee

উত্তর:


190

আপনি বাশের প্যারামিটার সম্প্রসারণ বৈশিষ্ট্যটি ব্যবহার করতে পারেন

for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done

স্পেস সহ ফাইলের নামের জন্য উদ্ধৃতি প্রয়োজন।


1
আমি এটি খুব পছন্দ করি তবে এটি ব্যাশ-নির্দিষ্ট বৈশিষ্ট্যগুলি ব্যবহার করে ... আমি সাধারণত এগুলিকে "স্ট্যান্ডার্ড" শ এর পক্ষে ব্যবহার করি না।
দিয়েগো সেভিলা

2
দূরে এক লাইনের ইন্টারেক্টিভ স্টাফের জন্য আমি সবসময় সেড-ফু এর পরিবর্তে এটি ব্যবহার করি। যদি এটি স্ক্রিপ্ট হয়, হ্যাঁ, বাশিজম এড়িয়ে চলুন।
richq

একটি সমস্যা আমি কোড সহ পেয়েছি: যদি ফাইলগুলি ইতিমধ্যে নামকরণ করা হয় এবং আমি আবার চালিত করি তবে কি হবে? আমি নিজের একটি উপ-ডিরেক্টরিতে যাওয়ার চেষ্টা করার জন্য সতর্কতা পেয়েছি।
জেরেমি এল

1
পুনরায় সঞ্চালনের ত্রুটিগুলি এড়াতে আপনি " .pkg" অংশে একই প্যাটার্নটি ব্যবহার করতে পারেন , অর্থাত্ "আই ইন ইন * - [0-9।] .Pkg; do এমভি $ i $ {i / - [0-9 ।] *। pkg / .pkg}; সম্পন্ন "। তবে ত্রুটিগুলি যথেষ্ট নিরীহ (একই ফাইলে চলে যাওয়া)।
richq

3
কোনও বাশ সমাধান নয়, তবে আপনি যদি পার্ল ইনস্টল করেছেন তবে এটি ব্যাচের নাম পরিবর্তনের জন্য সহজ পুনর্নবীকরণ কমান্ড সরবরাহ করে, কেবল করুনrename "s/-[0-9.]*//" *.pkg
রুফাস

33

সমস্ত ফাইল একই ডিরেক্টরিতে থাকলে ক্রম

ls | 
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' | 
sh

তোমার কাজ করবে Sed কমান্ড একটি ক্রম তৈরি করবে এমভি , কমান্ড যা আপনি করতে পারেন তারপর শেলে নল। প্রথমে ট্রেইলিং | shনা করে পাইপলাইন চালানো ভাল, যাতে কমান্ডটি যা চান তা নিশ্চিত করে নিন।

একাধিক ডিরেক্টরি মাধ্যমে পুনরাবৃত্তি কিছু ব্যবহার করুন

find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh

নোট যে sed রেগুলার এক্সপ্রেশন ক্রম গোষ্ঠীবদ্ধ একটি ব্যাকস্ল্যাশ পূর্বে বন্ধনী হয়, \(এবং \)বরং একক বন্ধনী চেয়ে (এবং )


আমার নির্মোহকে ক্ষমা করুন, কিন্তু ব্যাকস্ল্যাশগুলি সহ বন্ধনীগুলি ছেড়ে যাওয়া কী তাদেরকে আক্ষরিক চরিত্র হিসাবে বিবেচনা করবে?
ডিভাইস 1

2
ইন গোষ্ঠীবদ্ধ ক্রম (বরং একটি একক বন্ধনী চেয়ে রেগুলার এক্সপ্রেশন sed।
Diomidis Spinellis

আমার জন্য কাজ করে নি, আপনার সাহায্য পেয়ে খুশি হবে .... FROM ফাইলটির প্রত্যয়টি TO ফাইলটিতে যুক্ত হয়েছে: $ সন্ধান করুন। -প্রকার ডি | sed -n 's /(.*)\/(.*) anysoftkeyboard (। *) / mv "\ 1 \ / an 2anysoftkeyboard \ 3" "\ 1 \ / \ 2Effectedkeyboard \ 3" / p' | sh >> >>>>> আউটপুট >>>> এমভি: পুনঃনামকরণ ./base/src/main/java/com/anysoftkeyboard/base/d অভিধান থেকে। : এই জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই
ভিটালি পম

মনে হচ্ছে বন্ধনীগুলিতে আপনি ব্যাকস্ল্যাশ মিস করছেন।
ডায়োমিডিস স্পিনেলিস

1
lsস্ক্রিপ্টগুলিতে ব্যবহার করবেন না । প্রথম বৈচিত্র্য অর্জন করা যেতে পারে printf '%s\n' * | sed ...এবং কিছু সৃজনশীলতার সাথে আপনি সম্ভবত এটি sedথেকেও মুক্তি পেতে পারেন । বাশের printfএকটি '%q'ফর্ম্যাট কোড অফার করে যা কার্যকর হতে পারে যদি আপনার কাছে এমন ফাইলের নাম থাকে যাতে আক্ষরিক শেল মেটাচার্যাক্টর থাকে।
ট্রিপলি

10

আমি এরকম কিছু করব:

for file in *.pkg ; do
    mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done

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

সম্পাদনা : এছাড়াও, এই সংস্করণটি উপরের অন্যদের মতো কোনও ব্যাশ-নির্দিষ্ট বৈশিষ্ট্য ব্যবহার করে না, যা আপনাকে আরও বহনযোগ্যতার দিকে নিয়ে যায়।


তারা সবাই একই ডিরেক্টরিতে রয়েছে। আপনি আরকিউ এর উত্তর সম্পর্কে কি মনে করেন?
জেরেমি এল

আমি ব্যাশ-নির্দিষ্ট বৈশিষ্ট্যগুলি না ব্যবহার করতে চাই তবে তার পরিবর্তে আরও মানক শ।
দিয়েগো সেভিলা

1
আমি ধরে নিয়েছি এটি একটি দ্রুত নামকরণের জন্য, পরবর্তী প্রজন্মের ক্রস প্ল্যাটফর্ম, পোর্টেবল এন্টারপ্রাইজ অ্যাপ্লিকেশন ;-)
সমৃদ্ধ

1
হাহাহা, যথেষ্ট ন্যায্য ... আমার মতো বহনযোগ্য মনোভাবের মানুষটির বাইরে :)
ডিয়েগো সেভিলা

এটি তৃতীয় উদাহরণ হিসাবে অ্যাকাউন্ট করে না: xorg-libXrandr (নামে হাইফেন ব্যবহৃত হয়)।
জেরেমি এল

5

এখানে বর্তমানে গৃহীত উত্তরের সমতুল্য একটি পসিক্স রয়েছে । এটি ${variable/substring/replacement}কোনও বাউর্ন-সামঞ্জস্যপূর্ণ শেল উপলভ্য বাশ-কেবলমাত্র প্যারামিটার বিস্তারের বাণিজ্য করে ।

for i in ./*.pkg; do
    mv "$i" "${i%-[0-9.]*.pkg}.pkg"
done

প্যারামিটার সম্প্রসারণ মুছে ফেলা ম্যাচের সাথে প্রত্যয় সহ ${variable%pattern}মান তৈরি করে । ( একটি উপসর্গ অপসারণ করতে হবে।)variablepattern${variable#pattern}

আমি -[0-9.]*গ্রহণযোগ্য উত্তর থেকে সাবপ্যাটার্নটি রেখেছি যদিও এটি সম্ভবত বিভ্রান্তিকর। এটি কোনও নিয়মিত প্রকাশ নয়, তবে একটি গ্লোব প্যাটার্ন; সুতরাং এর অর্থ এই নয় যে "শূন্য বা তার বেশি সংখ্যার বা বিন্দুগুলির পরে একটি ড্যাশ"। পরিবর্তে, এর অর্থ "একটি ড্যাশ, তার পরে একটি সংখ্যা বা একটি বিন্দু, তার পরে কিছু"। "কিছু" সম্ভবততমতম ম্যাচ হবে, সবচেয়ে দীর্ঘতম নয়। (বাশ প্রস্তাব দেয় ##এবং %%সংক্ষিপ্ততমের চেয়ে দীর্ঘতম সম্ভাব্য উপসর্গ বা প্রত্যয় ছাঁটাইয়ের জন্য))


5

আমরা ধরে নিতে পারি যে sedকোনও * নিক্স পাওয়া যায়, তবে আমরা নিশ্চিত হতে পারি না যে এটি sed -nএমভি কমান্ড উত্পন্ন করতে সমর্থন করবে । ( দ্রষ্টব্য: কেবল জিএনইউ)sed করে))

তবুও, ব্যাশ বিল্টিনস এবং সেড, আমরা এটির জন্য দ্রুত একটি শেল ফাংশন হুইপ করতে পারি।

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

ব্যবহার

sedrename 's|\(.*\)\(-[0-9.]*\.pkg\)|\1\2|' *.pkg

before:

./Xft2-2.1.13.pkg
./jasper-1.900.1.pkg
./xorg-libXrandr-1.2.3.pkg

after:

./Xft2.pkg
./jasper.pkg
./xorg-libXrandr.pkg

লক্ষ্য ফোল্ডার তৈরি করা:

যেহেতু mvস্বয়ংক্রিয়ভাবে লক্ষ্য ফোল্ডারগুলি তৈরি করে না আমরা আমাদের প্রাথমিক সংস্করণটি ব্যবহার করতে পারি না sedrename

এটি মোটামুটি ছোট একটি পরিবর্তন, সুতরাং সেই বৈশিষ্ট্যটি অন্তর্ভুক্ত করে ভাল লাগবে:

আমাদের একটি ইউটিলিটি ফাংশন abspath(বা পরম পাথ) প্রয়োজন কারণ বাশের এই বিল্ডটি নেই।

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

একবার আমাদের কাছে আসার পরে আমরা একটি সেড / নামকরণ প্যাটার্নের জন্য লক্ষ্য ফোল্ডার (গুলি) তৈরি করতে পারি যার মধ্যে নতুন ফোল্ডার কাঠামো অন্তর্ভুক্ত থাকে।

এটি নিশ্চিত করবে যে আমরা আমাদের লক্ষ্যযুক্ত ফোল্ডারগুলির নাম জানি। আমরা যখন নাম পরিবর্তন করি তখন আমাদের লক্ষ্য ফাইলের নামে এটি ব্যবহার করতে হবে।

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

এখানে পুরো ফোল্ডার সচেতন স্ক্রিপ্ট ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

অবশ্যই, এটি এখনও কার্যকর হয় যখন আমাদের নির্দিষ্ট টার্গেট ফোল্ডার না থাকে।

যদি আমরা সমস্ত গান একটি ফোল্ডারে রাখতে চাই, ./Beethoven/ আমরা এটি করতে পারি:

ব্যবহার

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

বোনাস বৃত্তাকার ...

ফোল্ডার থেকে একক ফোল্ডারে ফাইল স্থানান্তর করতে এই স্ক্রিপ্টটি ব্যবহার করে:

ধরে নিই আমরা মিলে যাওয়া সমস্ত ফাইল সংগ্রহ করতে চেয়েছিলাম এবং সেগুলি বর্তমান ফোল্ডারে রেখে দিতে পারি, আমরা এটি করতে পারি:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

সেড রেজেক্স নিদর্শনগুলিতে নোট

নিয়মিত শেড প্যাটার্ন বিধিগুলি এই স্ক্রিপ্টে প্রয়োগ হয়, এই নিদর্শনগুলি পিসিআরই নয় (পার্ল সামঞ্জস্যপূর্ণ নিয়মিত এক্সপ্রেশন)। আপনি sed -rবা sed -E আপনার প্ল্যাটফর্মের উপর নির্ভর করে নিয়মিত প্রকাশের বাক্য গঠনকে বাড়িয়ে দিতে পারেন ।

man re_formatসেড বেসিক এবং এক্সটেন্ডেড রেজএক্সপেক্স নিদর্শনগুলির সম্পূর্ণ বিবরণের জন্য পসিক্স অনুগত দেখুন ।


4

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

আপনার উদাহরণের জন্য আমি করব:

rename 's/\d*?\.\d*?\.\d*?//' *.pkg

এর 'অর্থ বিকল্প'। ফর্মটি হ'ল সার্চ প্যাটার্ন / রিপ্লেসমেন্ট / ফাইল_ টু অ্যাপ্লিকেশন। আপনার এটির জন্য রেজিেক্স ব্যবহার করা দরকার যা সামান্য অধ্যয়ন করে তবে এটি প্রচেষ্টাটি ভাল।


আমি রাজী. একটি অনিয়মিত জিনিস, ব্যবহার করার জন্য forএবং sedইত্যাদি জরিমানা, কিন্তু এটা শুধু ব্যবহার দ্রুততর অনেক সহজ এবং renameআপনি নিজেকে প্রায়ই এই কাজ।
আরজেন্টাম 2f

আপনি কি পিরিয়ড এড়ানো?
বড় অর্থ

সমস্যাটি হ'ল এটি পোর্টেবল নয়; কেবলমাত্র সমস্ত প্ল্যাটফর্মেরই renameকমান্ড থাকে না; উপরন্তু, কিছু একটা থাকবে বিভিন্ন rename বিভিন্ন বৈশিষ্ট্য, সিনট্যাক্স, এবং / অথবা বিকল্প সহ কমান্ড। এটি পার্লের মতো দেখাচ্ছে renameযা মোটামুটি জনপ্রিয়; তবে উত্তরটির সত্যই এটি স্পষ্ট করা উচিত।
ট্রিপলি

3

এর জন্য আরও ভাল ব্যবহার sed, এরকম কিছু:

find . -type f -name "*.pkg" |
 sed -e 's/((.*)-[0-9.]*\.pkg)/\1 \2.pkg/g' |
 while read nameA nameB; do
    mv $nameA $nameB;
 done

নিয়মিত অভিব্যক্তিটি সন্ধান করা একটি অনুশীলন হিসাবে ছেড়ে যায় (যেমন ফাইলের সাথে কাজ করে যা স্পেস অন্তর্ভুক্ত করে)


ধন্যবাদ: নামগুলিতে স্পেস ব্যবহার করা হয় না।
জেরেমি এল

1

এটি ধরে নিলে কাজ হবে বলে মনে হচ্ছে

  • $ pkg দিয়ে সবকিছু শেষ হয়
  • আপনার সংস্করণ # এর সর্বদা একটি "-" দিয়ে শুরু হয়

.pkg কে স্ট্রিপ করুন, তারপরে স্ট্রিপ অফ করুন - ..

for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done

কিছু প্যাকেজ রয়েছে যার নামে হাইফেন রয়েছে (তৃতীয় উদাহরণ দেখুন)। এটি কি আপনার কোডকে প্রভাবিত করে?
জেরেমি এল

1
আপনি একাধিক সেড এক্সপ্রেশন ব্যবহার করে চালাতে পারেন -e। যেমন sed -e 's/\.pkg//g' -e 's/-.*//g'
tacot মঙ্গলবার

lsআউটপুটকে বিশ্লেষণ করবেন না এবং আপনার ভেরিয়েবলগুলি উদ্ধৃত করবেন না শেল স্ক্রিপ্টগুলিতে সাধারণ সমস্যা এবং অ্যান্টিপ্যাটার্নগুলি নির্ণয়ের জন্য শেলচেক.net দেখুন ।
ট্রিপলি

1

আমার একাধিক *.txtফাইল .sqlএকই ফোল্ডারের হিসাবে নামকরণ করা ছিল। নীচে আমার জন্য কাজ করেছে:

for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done

2
আপনি নিজের উত্তরটি এপি-র প্রকৃত ব্যবহারের ক্ষেত্রে বিমূর্ত করে উন্নত করতে পারেন।
ডাকব

এটিতে একাধিক সমস্যা রয়েছে পাশাপাশি একটি সুস্পষ্ট বাক্য গঠন ত্রুটি রয়েছে। একটি শুরুর জন্য শেলচেক . net দেখুন ।
ট্রিপলি

0

এই উত্তরের জন্য আপনাকে ধন্যবাদ। আমারও কিছুটা সমস্যা ছিল। .Nzb.queued ফাইলগুলি .nzb ফাইলগুলিতে সরানো হচ্ছে। ফাইলের নামগুলিতে এর স্পেস এবং অন্যান্য ক্রাফট ছিল এবং এটি আমার সমস্যার সমাধান করেছে:

find . -type f -name "*.nzb.queued" |
sed -ne "s/^\(\(.*\).nzb.queued\)$/mv -v \"\1\" \"\2.nzb\"/p" |
sh

এটি ডায়োমিডিস স্পিনেলিসের উত্তরের ভিত্তিতে তৈরি।

রেজেক্স পুরো ফাইলনামের জন্য একটি গ্রুপ এবং .nzb.queued এর আগে অংশের জন্য একটি গ্রুপ তৈরি করে এবং তারপরে একটি শেল মুভ কমান্ড তৈরি করে। স্ট্রিং উদ্ধৃত সঙ্গে। এটি শেল স্ক্রিপ্টে একটি লুপ তৈরি করা এড়িয়ে যায় কারণ এটি ইতিমধ্যে শেড দ্বারা সম্পন্ন হয়েছে।


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