কীভাবে একাধিক ফাইলের নাম পরিবর্তন করবেন find


37

কমান্ড findকমান্ডটি ব্যবহার করে আমি একাধিক ফাইলের নামকরণ করতে চাই (ফাইল 1 ... ফাইলনে ফাইল 1_ নামকরণ ... ফাইলন_রেম)

find . -type f -name 'file*' -exec mv filename='{}' $(basename $filename)_renamed ';'

কিন্তু এই ত্রুটি পেয়ে:

mv: cannot stat filename=./file1’: No such file or directory

এটি কাজ করছে না কারণ ফাইলের নামটি শেল ভেরিয়েবল হিসাবে ব্যাখ্যা করা হয়নি।

উত্তর:


46

নিম্নলিখিতটি আপনার পদ্ধতির সরাসরি সমাধান:

find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;

তবে আপনার কাছে প্রচুর mvম্যাচের ফাইল থাকলে এটি খুব ব্যয়বহুল, কারণ আপনি প্রতিটি ম্যাচের জন্য একটি তাজা শেল (যেটি কার্যকর করে ) শুরু করে । এবং যদি আপনার কোনও ফাইলের নামে মজার অক্ষর থাকে তবে এটি বিস্ফোরিত হবে। আরও কার্যকর ও সুরক্ষিত পদ্ধতি হ'ল:

find . -type f -name 'file*' -print0 | xargs --null -I{} mv {} {}_renamed

এটিতে অদ্ভুত নামযুক্ত ফাইলগুলির সাথে কাজ করার সুবিধাও রয়েছে। যদি findএটি সমর্থন করে তবে এটিকে কমিয়ে আনা যায়

find . -type f -name 'file*' -exec mv {} {}_renamed \;

xargsযখন ব্যবহার করছেন না সংস্করণ দরকারী {}হিসাবে,

find .... -print0 | xargs --null rm

এখানে rmএকবার কল করা হয় (বা বেশ কয়েকটিবার ফাইলের সাথে কয়েকবার) তবে প্রতিটি ফাইলের জন্য নয়।

আমি basenameআপনার প্রশ্নটি সরিয়ে দিয়েছি , কারণ এটি সম্ভবত ভুল: আপনি চলে foo/bar/file8যান file8_renamed, না foo/bar/file8_renamed

সম্পাদনা (মতামত হিসাবে প্রস্তাবিত):

  • findছাড়া সংক্ষিপ্ত যোগ করা হয়েছেxargs
  • সুরক্ষার স্টিকার যুক্ত হয়েছে

ক্ষেত্রে xঅনর্থক: find . -type f -name 'file*' -exec mv {} "{}_renamed" \; xargsসংস্করণটির প্রথম উদাহরণের মতো দক্ষতা রয়েছে /
কোস্টাস

xআছে কেবল সরাসরি প্রশ্নকর্তা এর পদক্ষেপ সমাধান করুন।
টমাস এরকার

2
(1) {}শেল ( sh -c "…") কমান্ডে সরাসরি ব্যবহার করা খুব বিপজ্জনক - আপনার সর্বদা এটি আর্গুমেন্ট হিসাবে পাস করা উচিত। (2) সমস্ত সংস্করণ নির্মাণ findসমর্থন করে না {}_renamed। (3) আমি আপনার বক্তব্যটি xargsফাইলগুলি অপসারণের জন্য দরকারী (তাদের নাম পরিবর্তনের বিপরীতে) বুঝতে পারি না ।
জি-ম্যান

@ জি-ম্যান: এর সাথে পার্থক্যটি বনাম xargsনয় , বরং বনামের ব্যবহার । পূর্ববর্তীটি একই সাথে একইরকম হয় যখন দ্বিতীয়টি হয় । mvrm{}mv file1 file1_renamed; mv file2 file2_renamedrm file1 file2
থমাস এরকার

1
এবং যদি আপনি _ নামকরণ করা ফাইলগুলি তাদের মূল নামগুলিতে ফিরে যেতে চান তবে আপনি কীভাবে তা করবেন?
এমসিএমিলাব

17

প্রথম উত্তরটি চেষ্টা করার পরে এবং এটির সাথে সামান্য চেষ্টা করার পরে আমি দেখতে পেলাম যে এটি ব্যবহার করে কিছুটা ছোট এবং কম জটিল করা যায় -execdir:

find . -type f -name 'file*' -execdir mv {} {}_renamed ';'

দেখে মনে হচ্ছে এটি আপনার যা প্রয়োজন ঠিক ঠিক তা করা উচিত।


2
সঙ্গে findবাস্তবায়নের যে সমর্থন -execdirএবং {}সামগ্রিকভাবে না, এটি সবচেয়ে নিরাপদ নয়। আপনি একটি যোগ করতে চান করতে পারেন -iথেকে mvযদিও (এবং -Tযদি আপনার mvএটা সমর্থন করে)
Stéphane Chazelas

1
@ স্টাফেনচাজেলাস আরও ভাল, mvপ্রম্পটের উপর নির্ভর করার পরিবর্তে বা এটির পরিবর্তে, আপনি (আপনার প্রয়োগটি এটি findসমর্থন করে কিনা তার উপর নির্ভর করে) সন্দেহাতীতভাবে এটিও ব্যবহার করতে পারেন -okdirযা কার্যকর করার আগে কমান্ডটি কার্যকর করার আগে আউটপুট দেয় will
মতিজস

-depthআপনি ডিরেক্টরি নামও স্পর্শ করতে চলেছেন যদি উল্লেখযোগ্য যে এটি একটি ভাল ধারণা।
সিরো সান্তিলি 事件 改造 中心 法轮功 六四 事件

আরগ, সবেমাত্র পাওয়া গেছে যে -execdirএকটি খুব বিরক্তিকর নেতিবাচক দিক রয়েছে, কোনও আপেক্ষিক পাথ findথাকলে কিছু করতে অস্বীকৃতি জানায় PATH... জিজ্ঞাসাবাবু find: The relative path XXX is included in the PATH environment
সান্তিলি 事件 改造 中心 法轮功 六四 事件

6

আর একটি পদ্ধতি হ'ল আউটপুট থেকে while readলুপ ব্যবহার করা find। এই পরিবর্তনশীল করে একটি পৃথক ডিম ছাড়ার অতিরিক্ত খরচ / সম্ভাব্য নিরাপত্তা বিষয় সম্পর্কে চিন্তা না করেও কাজে ব্যবহৃত হতে পারে প্রতিটি ফাইলের নাম এক্সেস পারবেন sh -cপ্রক্রিয়া ব্যবহার করে findএর -execবিকল্প।

find . -type f -name 'file*' |
    while IFS= read file_name; do
        mv "$file_name" "${file_name##*\/}_renamed"
    done

এবং ব্যবহৃত শেলটি যদি -dএকটি readডিলিমিটার নির্দিষ্ট করার বিকল্পটিকে সমর্থন করে তবে আপনি নিম্নলিখিতটি ব্যবহার করে অদ্ভুতভাবে নামযুক্ত ফাইলগুলি (যেমন একটি নতুন লাইন সহ) সমর্থন করতে পারেন:

find . -type f -name 'file*' -print0 |
    while IFS= read -d '' file_name; do
        mv "$file_name" "${file_name##*\/}_renamed"
    done

3

আমি প্রথম উত্তরে প্রসারিত করতে চাই এবং নোট করব যে এটি ফাইলের সাথে যুক্ত করতে কাজ করবে না যেহেতু ./পাথ উপসর্গ ফাইলের যুক্তিতে উপস্থিত রয়েছে।

থমাস এরকারের উত্তরটি সংশোধন করে আমি এটিকে আরও জেনেরিক পদ্ধতি বলে মনে করি

find . -name PATTERN -printf "%f\0" | xargs --null -I{} mv {} "prefix {} suffix"

xargs বিকল্পগুলি:

--nullইঙ্গিত করে যে প্রতিটি যুক্তি stdinনাল অক্ষর ( \0) দিয়ে শেষ হয় । এইভাবে ফাইলনামে ফাঁকা স্থান থাকতে পারে, অন্যথায় প্রতিটি শব্দ mvকমান্ডের জন্য আলাদা প্যারামিটার হিসাবে ছড়িয়ে দেওয়া হবে ।

-I replace-strপ্রতিটি সূত্রটি replace-strপড়ার তর্ক দিয়ে প্রতিস্থাপন করা হবে stdin। সুতরাং, আপনি অন্য স্ট্রিং এর প্রয়োজন হলে এটি পরিবর্তন করতে পারেন।


এর pringf "%f\0"পরিবর্তে কেন print0?
slm

1
@sim, কারণ -print0ইচ্ছার উত্পাদন ./উপসর্গ যদি PATTERNশেল metacharacters যখন এমন কিছু বিষয় যা উপসর্গ মূল নামের পুনঃনামকরনের যা ভাবে পেতে রয়েছে। (যেমন পুনঃনামকরণ 0 - foo.txtকরা 00 - foo.txt, 1 - bar.txtথেকে 01 - bar.txtইত্যাদি)
দাশ-G

2

আমি সঙ্গে অনুরূপ কিছু করতে সক্ষম ছিল for, findএবং mv

for i in $(find . -name 'config.yml'); do mv $i $i.bak; done

এটি সমস্ত config.ymlফাইল সন্ধান করে এবং এগুলিতে নাম পরিবর্তন করেconfig.yml.bak


এটি ভেরিয়েবল প্রসারণ যেমন, ব্যবহার করতে সক্ষম হওয়ার সুবিধা রয়েছে। $ {I: R}। চমৎকার উত্তর.
সালামি

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