ফাইন্ড কমান্ড থেকে পাইপযুক্ত ফাইলের নাম ম্যানিপুলেট করুন


10

আমি বাশের তুলনায় তুলনামূলকভাবে নতুন এবং এমন কিছু করার চেষ্টা করছি যা পৃষ্ঠের উপরে বেশ সোজা মনে হয়েছিল - * .wma ফাইলগুলির সমস্ত পেতে একটি ডিরেক্টরি বিকাশ অনুসন্ধান করুন, সেই আউটপুটটিকে একটি কমান্ডে পাইপ করুন যেখানে আমি তাদের এমপি 3 এ রূপান্তর করি এবং রূপান্তরিত ফাইল .mp3 হিসাবে সংরক্ষণ করুন। আমার ধারণাটি হ'ল কমান্ডটি নিম্নলিখিতগুলির মতো হওয়া উচিত (আমি অডিও রূপান্তর কমান্ডটি ছেড়ে দিয়েছি এবং পরিবর্তে চিত্রের জন্য প্রতিধ্বনি ব্যবহার করছি):

$ find ./ -name '*.wma' -type f -print0 | xargs -0 -I f echo ${f%.*}.mp3

যেহেতু আমি এটি বুঝতে পেরেছি,--প্রিন্ট0 আরগটি আমাকে ফাইল নামগুলি হ্যান্ডেল করতে দেবে যাতে স্পেস রয়েছে (যা অনেকে মিউজিক ফাইল হিসাবে এটি করেন)। তারপরে আমি প্রত্যাশা করছি (xargs এর ফলস্বরূপ) যে অনুসন্ধানের প্রতিটি ফাইল পাথ চ'তে ক্যাপচার করা হয়েছে, এবং স্ট্রিংয়ের ম্যাচটি / স্ট্রিংয়ের শেষে থেকে মুছুন তা ব্যবহার করে আমি এমপি 3 দিয়ে মূল ফাইলের পথটি প্রতিধ্বনিত করব WMA এর পরিবর্তে এক্সটেনশন instead তবে, এই ফলাফলের পরিবর্তে, আমি নিম্নলিখিতগুলি দেখছি:

*.mp3
*.mp3
*.mp3
*.mp3
*.mp3
*.mp3
*.mp3
*.mp3
*.mp3
...

সুতরাং আমার প্রশ্নটি (এখানে 'আমি কী ভুল করছি' নির্দিষ্ট করে বাদে) - এটি হল - পাইপের ক্রিয়াকলাপের ফলস্বরূপ মানগুলি একটি পরিবর্তনশীল অ্যাসাইনমেন্টের ফলাফলের চেয়ে স্ট্রিং ম্যানিপুলেশন অপারেশনগুলিতে আলাদাভাবে চিকিত্সা করা দরকার do ?


1
এর xargsসাথে ব্যবহার করার কোনও কারণ নেই find। এটি একটি -execবিকল্প সঙ্গে আসে । আপনি কি আপনার প্রশ্নে কেবল যে আদেশটি ব্যবহার করতে চলেছেন তা যুক্ত করতে পারেন, এবং কেউ আপনাকে সঠিক findআদেশটি প্রদর্শন করতে পারে ?
ixtmixilix

হ্যাঁ (আমি যেমন নীচে উল্লেখ করেছি), যতক্ষণ না আমি এখনও {}
ফাইন্ড

প্রকৃতপক্ষে প্রান্তের কেসগুলি xargsআরও উপযুক্ত যেখানে রয়েছে exec। এই stackpost দেখুন stackoverflow.com/questions/896808/find-exec-cmd-vs-xargs বিন্দু একটি কেস জন্য।
d34dh0r53

@ d34dh0r53 কোন প্রান্তের মামলা? আপনার সাথে সংযুক্ত থ্রেডটি কোনও নির্দেশ করে না।
গিলেস 'তাই খারাপ হওয়া বন্ধ করুন'

উত্তর:


8

অন্যান্য উত্তর যেমন ইতিমধ্যে চিহ্নিত করেছে, কমান্ড ${f%.*}চালানোর আগে শেল দ্বারা এটি প্রসারিত হয় xargs। প্রতিটি ফাইলের নামের জন্য শেল ভেরিয়েবলটি ফাইলের নামের সাথে fসেট করার সাথে আপনার এই সম্প্রসারণটি হওয়া দরকার (পাসিং এটি -I fকরে না: xargsশেল ভেরিয়েবলের কোনও ধারণা নেই), এটি fকমান্ডের স্ট্রিংটি সন্ধান করে, যদি আপনি চান যেমন যেমন xargs -I e echo …এটি কার্যকর করা কমান্ড থাকতে পারে ./somedir/somefile.wmacho .mp3)।

এই পদ্ধতির উপর নির্ভর করে, xargsএমন শেলটি চালিত করতে বলুন যা প্রসার সম্পাদন করতে পারে। আরও ভাল, বলুন find- xargsএকটি বৃহত্তর অপ্রচলিত সরঞ্জাম এবং সঠিকভাবে ব্যবহার করা শক্ত কারণ সন্ধানের আধুনিক সংস্করণগুলিতে কম নদীর গভীরতানির্ণয় অসুবিধা সহ একই কাজ (এবং আরও অনেক) কাজ করে এমন একটি কনস্ট্রাক্ট রয়েছে। পরিবর্তে find … -print0 | xargs -0 command …, চালান find … -exec command … {} +

find . -name '*.wma' -type f -exec sh -c 'for f; do echo "${f%.*}.mp3"; done' _ {} +

যুক্তি _হল $0শেল মধ্যে; ফাইলের নামগুলি অবস্থানগত আর্গুমেন্ট হিসাবে পাস হয়ে যায় যা for f; do …লুপ হয়। এই কমান্ডের একটি সহজ সংস্করণ প্রতিটি ফাইলের জন্য পৃথক শেল চালায় যা সমান তবে কিছুটা ধীর:

find . -name '*.wma' -type f -exec sh -c 'echo "${0%.*}.mp3"' {} \;

আপনার আসলে findএখানে ব্যবহার করার দরকার নেই, ধরে নিচ্ছেন আপনি সাম্প্রতিকতম শেলটি চালাচ্ছেন (ksh93, ব্যাশ -4.0, বা zsh)। ব্যাশ সালে করা shopt -s globstarআপনার .bashrcসক্রিয় করতে **/(ksh যে এর সাব মধ্যে recurse করার উল্লিখিত glob প্যাটার্ন set -o globstar)। তাহলে আপনি চালাতে পারেন

for f in **/*.wma; do
  echo "${f%.*}.mp3"
done

(যদি আপনার কাছে ডিরেক্টরি বলা হয় তবে লুপের শুরুতে *.wmaযুক্ত করুন [ -f "$f" ] || continue))


দুর্দান্ত ব্যাখ্যার পাশাপাশি আমাকে এমন একটি দিক নির্দেশিত করে যা আমি বুঝতেও পারি নি (গ্লোবস্টারের কার্যকারিতা পেতে আমার ব্যাশ শেলকে উন্নীত করা) - শেষ পর্যন্ত, পুনরাবৃত্ত গ্লোব্বিং হ'ল এমন একটি সমাধান যা কমান্ডকে সহজ করে দিয়েছিল এবং আমি যা করার চেষ্টা করছিলাম তার সব কিছুই সম্পাদন করে that । ধন্যবাদ!
হাওয়ার্ড ডায়ারিং

6

আপনার সমাধানের ক্ষেত্রে $ {f%। *}। এমপি 3 শেলটিতে সম্পন্ন করা হয় যে আপনি পুরো কমান্ডটি সাইন ইন করছেন, জার্গার্স দ্বারা তৈরি শেলটিতে নয় । এবং আপনার শেলের মধ্যে কোনও ভেরিয়েবল নেই, এটি একটি খালি স্ট্রিং দ্বারা প্রতিস্থাপিত হয়।

সলিউশন ব্যবহার xargs সঙ্গে -আমি চ :

% cat 1.sh 
#!/bin/sh
f=$1
echo ${f%.*}.mp3
% /bin/ls -1
1.sh
aaa.wma
bbbb.wma
ccccc.wma
% find ./ -name '*.wma' -type f -print0 | xargs -0 -I f ./1.sh f
./aaa.mp3
./ccccc.mp3
./bbbb.mp3

তবে আমি এটি এইভাবে করব:

% find ./ -name '*.wma' -type f | sed 's,\.wma$,.mp3,'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.