আপনার স্ক্রিপ্টে বেশ কয়েকটি সমস্যা রয়েছে।
প্রথমত, কোনও ভেরিয়েবলের কমান্ডের ফলাফল নির্ধারণের জন্য আপনাকে এটি ব্যাকটিক্স ( `command`
) বা, পছন্দসই, দ্বারা আবদ্ধ করতে হবে $(command)
। এটি আপনার একক উদ্ধৃতিতে ( 'command'
) রয়েছে যা আপনার কমান্ডের ফলাফলটি আপনার ভেরিয়েবলের কাছে বরাদ্দ করার পরিবর্তে কমান্ডটিকে একটি স্ট্রিং হিসাবে নির্ধারণ করে। অতএব, আপনার test
আসলে:
$ echo "test $sum1=$sum2"
test find $i -type f -iname "*.jpg" -exec md5sum {} \;=find $j -type f -iname "*.jpg" -exec md5sum {} \;
পরবর্তী সমস্যা হ'ল কমান্ডটি md5sum
কেবল হ্যাশের চেয়ে বেশি ফেরত দেয়:
$ md5sum /etc/fstab
46f065563c9e88143fa6fb4d3e42a252 /etc/fstab
আপনি কেবল প্রথম ক্ষেত্রের তুলনা করতে চান, সুতরাং আপনার প্রথম md5sum
আউটপুটটি কেবল একটি প্রিন্ট মুদ্রণকারী একটি কমান্ডের মাধ্যমে পার্স করা উচিত :
find $i -type f -iname "*.png" -exec md5sum '{}' \; | cut -f 1 -d ' '
অথবা
find $i -type f -iname "*.png" -exec md5sum '{}' \; | awk '{print $1}'
এছাড়াও, find
কমান্ডটি অনেকগুলি ম্যাচ ফিরিয়ে দেবে, কেবল একটি নয় এবং সেই ম্যাচগুলির প্রত্যেকটি দ্বিতীয় দ্বারা নকল করা হবে find
। এর অর্থ এই যে কিছু সময়ে আপনি নিজেই একই ফাইল তুলনা করা হবে, একাধিক md5sum অভিন্ন হবে এবং আপনি মোছার শেষ হবে সব আপনার ফাইল (আমি একটি পরীক্ষা Dir ধারণকারী এই দৌড়ে a.jpg
এবং b.jpg
):
for i in $(find . -iname "*.jpg"); do
for j in $(find . -iname "*.jpg"); do
echo "i is: $i and j is: $j"
done
done
i is: ./a.jpg and j is: ./a.jpg ## BAD, will delete a.jpg
i is: ./a.jpg and j is: ./b.jpg
i is: ./b.jpg and j is: ./a.jpg
i is: ./b.jpg and j is: ./b.jpg ## BAD will delete b.jpg
আপনি ডিরেক্টরি পরিচালনা করতে না পারলে আপনি চালনা করতে চান না for i in directory_path
passing এই সমস্ত ফাইল যদি একই ডিরেক্টরিতে থাকে তবে আপনি চালাতে চান for i in $(find directory_path -iname "*.jpg"
) সমস্ত ফাইলের মধ্য দিয়ে যেতে।
এটা একটি খারাপ ধারণা ব্যবহার করতে for
খোঁজ আউটপুট সঙ্গে লুপ। আপনার while
লুপগুলি বা গ্লোববিং ব্যবহার করা উচিত :
find . -iname "*.jpg" | while read i; do [...] ; done
বা, যদি আপনার সমস্ত ফাইল একই ডিরেক্টরিতে থাকে:
for i in *jpg; do [...]; done
আপনার শেল এবং আপনি যে বিকল্পগুলি সেট করেছেন তার উপর নির্ভর করে আপনি সাব-ডাইরেক্টরিগুলিতে ফাইলগুলির জন্য এমনকি গ্লোববিং ব্যবহার করতে পারেন তবে আসুন আমরা এখানে এটি .োকাতে পারি না।
অবশেষে, আপনার ভেরিয়েবলগুলি উদ্ধৃত করা উচিত অন্যথায় ফাঁকা জায়গাগুলির ডিরেক্টরি পাথগুলি আপনার স্ক্রিপ্টটি ভেঙে দেবে।
ফাইলের নামগুলিতে ফাঁক, নতুন লাইন, ব্যাকস্ল্যাশ এবং অন্যান্য অদ্ভুত অক্ষরগুলি থাকতে পারে, while
লুপের সাথে সঠিকভাবে মোকাবেলা করার জন্য আপনাকে আরও কিছু বিকল্প যুক্ত করতে হবে। আপনি যা লিখতে চান তা হ'ল:
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' i; do
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' j; do
if [ "$i" != "$j" ]
then
sum1=$(md5sum "$i" | cut -f 1 -d ' ' )
sum2=$(md5sum "$j" | cut -f 1 -d ' ' )
[ "$sum1" = "$sum2" ] && rm "$j"
fi
done
done
আরও সহজ উপায় হ'ল:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm $F[1]") if $k{$F[0]}>1'
একটি ভাল সংস্করণ যা ফাইলের নামের ফাঁকে ফাঁকে কাজ করতে পারে:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm \"@F[1 .. $#F]\"") if $k{$F[0]}>1'
এই ছোট্ট পার্ল স্ক্রিপ্টটি find
কমান্ডের ফলাফলগুলি (অর্থাত্ md5sum এবং ফাইলের নাম) দিয়ে চলবে । -a
জন্য বিকল্প perl
হোয়াইটস্পেস এ টুকরা ইনপুট লাইন এবং তাদের মধ্যে সংরক্ষণ করে F
অ্যারের, তাই $F[0]
একাধিক md5sum এবং থাকবে $F[1]
ফাইলের নাম। এমডি 5সাম হ্যাশে সংরক্ষিত হয়েছে k
এবং স্ক্রিপ্টটি হ্যাশটি ইতিমধ্যে দেখা গেছে কিনা তা পরীক্ষা করে দেখুন ( if $k{$F[0]}>1
) এবং এতে ফাইলটি মুছে ফেলা হলে ( system("rm $F[1]")
) রয়েছে।
এটি যখন কাজ করবে তখন এটি বৃহত্তর চিত্র সংগ্রহের জন্য খুব ধীর হবে এবং কোন ফাইলগুলি রাখতে হবে তা আপনি চয়ন করতে পারবেন না। অনেকগুলি প্রোগ্রাম রয়েছে যা এটিকে আরও মার্জিত উপায়ে পরিচালনা করে: