কমান্ড লাইন থেকে আমি একাধিক ফাইলের পুনরাবৃত্তভাবে কীভাবে এক্সটেনশন পরিবর্তন করব?


73

আমার কাছে .abcএক্সটেনশন সহ অনেকগুলি ফাইল রয়েছে এবং সেগুলিতে পরিবর্তন করতে চান .edefg
কমান্ড লাইন থেকে এটি কীভাবে করবেন?

আমার অনেকগুলি সাব-ফোল্ডার সহ একটি মূল ফোল্ডার রয়েছে, সুতরাং সমাধানটি পুনরাবৃত্তভাবে কাজ করা উচিত।


উত্তর:


85

একটি বহনযোগ্য উপায় (যা কোনও পসিক্স অনুবর্তী সিস্টেমের সাথে কাজ করবে):

find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;

Bash4 এ, আপনি পুনরাবৃত্ত গ্লোবগুলি পেতে (**) গ্লোবস্টার ব্যবহার করতে পারেন:

shopt -s globstar
for file in /the/path/**/*.abc; do
  mv "$file" "${file%.abc}.edefg"
done

renameউবুন্টুতে (পার্ল) কমান্ড পার্ল নিয়মিত এক্সপ্রেশন সিনট্যাক্স ব্যবহার করে ফাইলগুলির নাম পরিবর্তন করতে পারে, যা আপনি গ্লোবস্টারের সাথে একত্রিত করতে পারেন find:

# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)  

# Best to process the files in chunks to avoid exceeding the maximum argument 
# length. 100 at a time is probably good enough. 
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
  rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done

# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +

এছাড়াও http://mywiki.wooledge.org/BashFAQ/030 দেখুন


প্রথমটি কেবল পুরানোটির উপরে নতুন এক্সটেনশান যুক্ত করে, এটি প্রতিস্থাপন করে না ...
ব্যবহারকারীর 2757729

3
@ user2757729, এটি এটি প্রতিস্থাপন করে। শেষে ছাড়া ছাড়া "${1%.abc}"মান প্রসারিত । শেল স্ট্রিং ম্যানিপুলেশনগুলির জন্য আরও প্রায়শই জিজ্ঞাস্য 100 দেখুন । $1.abc
গিরিহা

আমি এটি একটি ~ 70k ফাইল ফাইল কাঠামোয় চালিয়েছি ... কমপক্ষে আমার শেলের মধ্যে এটি সম্ভবত এটি প্রতিস্থাপন করে নি।
ব্যবহারকারী2757729

1
@ user2757729 আপনি সম্ভবত "abc" রেখে গেছেন${1%.abc}...
কেভিএনএন

1
আন্ডারস্কোর প্রথম কমান্ডটিতে কী করছে সে সম্পর্কে অন্য কেউ যদি ভাবছেন, এটি দরকার কারণ sh -c প্রথম যুক্তিটির সাথে $ 0 নির্ধারিত করা হয়েছে এবং অবশিষ্ট বাকী সমস্ত আর্গুমেন্ট অবস্থানীয় পরামিতিগুলিতে বরাদ্দ করা হয়েছে । সুতরাং এটি _একটি ডামি আর্গুমেন্ট এবং ''} 'এর প্রথম অবস্থানগত যুক্তি sh -c
Hellobenallan

48

সমস্ত ফাইল একই ফোল্ডারে থাকলে এটি প্রয়োজনীয় কাজটি করবে

rename 's/.abc$/.edefg/' *.abc

ফাইলগুলির পুনরায় নামকরণ করতে পুনরাবৃত্তভাবে এটি ব্যবহার করুন:

find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'

8
অথবা rename 's/.abc$/.edefg/' /path/to/root/folder/**/*.abcব্যাশ একটি আধুনিক সংস্করণ হবে।
অ্যাডাম বাইরটেক

অ্যাডাম আমাকে পুনরাবৃত্তভাবে ফোল্ডারে * .abc কীভাবে ব্যবহার করতে পারেন তার জন্য একটি পরামর্শ প্রদান করার জন্য ধন্যবাদ!
রাফা সিয়ালাক

দুর্দান্ত টিপ, ধন্যবাদ! রেগেক্সের সিনট্যাক্সের সামান্য অংশ সম্পর্কে আমি আরও ডকুমেন্টেশন কোথায় পেতে পারি? কি ভালো লেগেছে sশুরুতে, এবং কি অন্যান্য অপশন আমি সেখানে ব্যবহার করতে পারেন। ধন্যবাদ!
এন্টার

@ অ্যাডামবাইরটেক আমি ইউটোপিকের বিষয়ে আপনার পরামর্শটি দিয়ে ব্যর্থ হয়েছি। ( 'কোন ধরণের ফাইলগুলিকে' বা কিছু যেমন।)
জোনাথন ওয়াই

14

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

আমি ব্যবহার findএর -execdirএই সমস্যা সমাধানের জন্য কর্ম। আপনি যদি এর -execdirপরিবর্তে ব্যবহার করেন -execতবে সুনির্দিষ্ট কমান্ডটি ম্যাচযুক্ত ফাইল সহ সাব-ডিরেক্টরি থেকে চালিত হবে। সুতরাং, পুরো পথটি পরিবর্তনের পরিবর্তে renameএটি কেবল পাস করে ./filename। এটি রেজিেক্সটি লিখতে অনেক সহজ করে তোলে।

find /the/path -type f \
               -name '*.abc' \
               -execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;

বিস্তারিত:

  • -type f মানে কেবল ফাইল অনুসন্ধান করা, ডিরেক্টরি নয়
  • -name '*.abc' মানে কেবলমাত্র ফাইল নামের সাথে মেলে যা .abc এ শেষ হয়
  • '{}'স্থানধারক যা সেই জায়গা চিহ্নিত করে যেখানে -execdirসন্ধানী পথটি প্রবেশ করানো হবে। একক-কোট প্রয়োজন হয়, এটি ফাঁকা এবং শেল অক্ষরের সাথে ফাইলের নামগুলি হ্যান্ডেল করার অনুমতি দেয়।
  • ব্যাকস্ল্যাশ পর -typeএবং -nameব্যাশ লাইন ধারাবাহিকতা চরিত্র আছে। আমি এই উদাহরণটি আরও পঠনযোগ্য করে তুলতে এগুলি ব্যবহার করি তবে আপনি যদি আপনার আদেশটি সমস্ত এক লাইনে রাখেন তবে তাদের প্রয়োজন হয় না।
  • তবে -execdirলাইনের শেষে ব্যাকস্ল্যাশ প্রয়োজন। এটি সেমিকোলন থেকে বাঁচতে পারে, যা চালিত কমান্ডটি সমাপ্ত করে -execdir। মজা!

রেজেক্সের ব্যাখ্যা:

  • s/ রেজেক্স শুরু
  • \.\/নেতৃস্থানীয়। / যে-এক্সেকডিরটি পাস করে মেলে the এবং / মেটাচার্যাক্টর (দ্রষ্টব্য: এই অংশটি আপনার সংস্করণের উপর নির্ভর করে পরিবর্তিত findহয় user ব্যবহারকারী @ অ্যাপলোর মন্তব্য দেখুন)
  • (.+)ফাইলের নাম মেলে। প্রথম বন্ধনগুলি পরে ব্যবহারের জন্য ম্যাচটি ক্যাপচার করে
  • \.abc বিন্দু থেকে বাঁচা, এবিসি সাথে মেলে
  • $ স্ট্রিংয়ের শেষে ম্যাচটি অ্যাঙ্কর করুন

  • / রেগেক্সের "ম্যাচ" অংশের শেষে এবং "প্রতিস্থাপন" অংশের শুরু চিহ্নিত করে

  • version1_ এই ফাইলটি প্রতিটি ফাইলের নামের সাথে যুক্ত করুন

  • $1বিদ্যমান ফাইলের নাম উল্লেখ করে, কারণ আমরা এটিকে প্রথম বন্ধনীতে ক্যাপচার করেছি। আপনি যদি "ম্যাচ" অংশে একাধিক সেট বন্ধনী ব্যবহার করেন তবে আপনি এখানে $ 2, $ 3 ইত্যাদি ব্যবহার করে উল্লেখ করতে পারেন them
  • .abcনতুন ফাইলের নাম .abc এ শেষ হবে। এখানে "প্রতিস্থাপন করুন" বিভাগে বিন্দু মেটাচার্যাক্টর এড়াতে হবে না
  • / রেজেক্সের শেষ

আগে

tree --charset=ascii

|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
    `-- nested_file.abc

পরে

tree --charset=ascii

|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
`-- dir1
    `-- version1_nested_file.abc

ইঙ্গিত: rename's -n বিকল্পটি দরকারী। এটি একটি শুকনো রান করে এবং আপনাকে কী নাম পরিবর্তন হবে তা দেখায়, তবে কোনও পরিবর্তন করে না।


বিশদ ব্যাখ্যার জন্য ধন্যবাদ, কিন্তু আশ্চর্যের বিষয়, যখন আমি এটি চেষ্টা করি তখন অগ্রভাগটি --execdirপাস করেনি ./যাতে \.\/রেজেক্সের অংশটি বাদ দেওয়া যায়। মে এর কারণ হ'ল আমি OSX এ থাকি উবুন্টু নয়
অ্যাপোলো

5

আর একটি বহনযোগ্য উপায়:

find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;

4
উবুন্টুকে জিজ্ঞাসা করুন স্বাগতম! যদিও এটি একটি মূল্যবান উত্তর, আমি আদেশটি কীভাবে এবং কেন কাজ করে তা ব্যাখ্যা করার জন্য (সম্পাদনা করে) এটি প্রসারিত করার পরামর্শ দিই ।
এলিয়াহ কাগান

3
# Rename all *.txt to *.text
for f in *.txt; do 
mv -- "$f" "${f%.txt}.text"
done

আপনার বিশ্লেষণ কেন করা উচিত নয় সে বিষয়ে এন্ট্রিটিও দেখুন ls

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

for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done

https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files


0

আমি যা চেয়েছিলাম ঠিক তেমনই আমি এটি করেছি এবং কাজ করেছি। আমি mvকমান্ডটি ব্যবহার করেছি । আমার একাধিক .3gpফাইল ছিল এবং আমি সেগুলির নতুন নামকরণ করতে চাই.mp4

এটির জন্য এখানে একটি সংক্ষিপ্ত অনেলাইনার রয়েছে:

for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done

যা কেবল বর্তমান ডিরেক্টরিতে স্ক্যান করে, সমস্ত .3gp ফাইল বাছাই করে, এরপরে নতুন নাম (এমভি ব্যবহার করে) ren-name_of_file.mp4


এটির নামকরণ file.3gpহবে file.3gp.mp4, যা বেশিরভাগ লোকেরা চান be
মারু

@ মুরু তবে নীতিটি এখনও বিদ্যমান। কেবল যে কোনও এক্সটেনশন নির্বাচন করুন তারপরে নাম পরিবর্তন করতে গন্তব্য এক্সটেনশানটি নির্দিষ্ট করুন। .3gpবা .mp4এখানে কেবল চিত্রের উদ্দেশ্যে ছিল।
খোফি

বাক্য গঠনটি পছন্দনীয়, ওয়ান-লাইনার এবং বোঝা সহজ। তবে আমি basename "$i" .mp4"ren- ren i.mp4" এর পরিবর্তে পূর্ববর্তী এক্সটেনশনটি সরিয়ে ফেলতে ব্যবহার করব ।
টাওপিআর

সত্য। ভাল যুক্তি.
খোফি

0

আমি এটি অর্জনের একটি সহজ উপায় খুঁজে পেয়েছি। Jpg থেকে pdf এ অনেক ফাইলের এক্সটেনশন পরিবর্তন করতে, ব্যবহার করুন:

for file in /path/to; do mv $file $(basename -s jpg $file)pdf ; done


0

ফাইল এবং ডিরেক্টরিগুলির সাথে নতুন নামকরণ করুন find -execdir | rename

আপনি যদি কেবল দুটি প্রত্যয় না দিয়ে ফাইল এবং ডিরেক্টরি দুটিরই নাম পরিবর্তন করতে চলেছেন তবে এটি একটি ভাল প্যাটার্ন:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find . -depth -execdir rename 's/findme/replaceme/' '{}' \;

ভয়ঙ্কর -execdirবিকল্পটি কমান্ডটি cdকার্যকর করার পূর্বে ডিরেক্টরিতে একটি করে rename, বিপরীতে -exec

-depth অনুপস্থিত অভিভাবক ডিরেক্টরিগুলির সাথে সম্ভাব্য সমস্যাগুলি রোধ করার জন্য পুনরায় নামকরণটি শিশুদের এবং তারপরে পিতামাতার ক্ষেত্রে ঘটে ensure

-execdir প্রয়োজনীয় কারণ নন-বেসনাম ইনপুট পাথগুলির সাথে নামটি ভাল খেলতে পারে না, যেমন নিম্নলিখিত ব্যর্থতা:

rename 's/findme/replaceme/g' acc/acc

PATHহ্যাকিং প্রয়োজনীয় কারণ -execdirএক খুব বিরক্তিকর অপূর্ণতা আছে: findঅত্যন্ত একগুঁয়ে হয় এবং নিয়ে কিছু করতে রাজি -execdirযদি আপনি আপনার যে কোন আপেক্ষিক পাথ আছে PATHএনভায়রনমেন্ট ভেরিয়েবল, যেমন ./node_modules/.bin, সঙ্গে ব্যর্থ:

সন্ধান করুন: আপেক্ষিক পথ './node_modules/.bin' PATH এনভায়রনমেন্ট ভেরিয়েবলের মধ্যে অন্তর্ভুক্ত করা হয়েছে, যা সন্ধানের-এক্সেকডির পদক্ষেপের সাথে একাত্মকভাবে সুরক্ষিত। দয়া করে entry PATH থেকে এন্ট্রিটি সরিয়ে দিন

আরও দেখুন: কেন '-execdir' ক্রিয়াকলাপটি PATH তে থাকা ডিরেক্টরিটির জন্য নিরাপত্তাহীন?

-execdirPOSIX- এ GNU অনুসন্ধান এক্সটেনশনrenameপার্ল ভিত্তিক এবং renameপ্যাকেজ থেকে আসে । উবুন্টুতে পরীক্ষা করা হয়েছে 18.10।

চেহারা অনুসারে নতুন নামকরণ করুন

যদি আপনার ইনপুট পাথগুলি না আসে findবা আপনি যদি যথেষ্ট পরিমাণে আপেক্ষিক বিরক্ত হন তবে আমরা কিছু পার্ল লুক হেড ব্যবহার করতে পারি ডিরেক্টরিগুলি নিরাপদে নামকরণ করতে:

git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'

আমি একটি সুবিধাজনক অ্যানালগ খুঁজে পেলাম না -execdirসঙ্গে xargs: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686

sort -rতা নিশ্চিত করার জন্য ফাইল, যেহেতু এখন আর পাথ একই প্রেফিক্স সহ খাটো বেশী পরে আসা তাদের নিজ নিজ ডিরেক্টরি পরে আসা প্রয়োজন।

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