কীভাবে একাধিক ফাইলের নাম পরিবর্তন করবেন 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.