এটি সম্পাদন করার জন্য বেশ কয়েকটি কার্যক্ষম উপায় রয়েছে।
আপনি যদি আপনার মূল সংস্করণটির সাথে ঘনিষ্ঠভাবে থাকতে চান তবে এটি এইভাবে করা যেতে পারে:
getlist() {
IFS=$'\n'
for file in $(find . -iname 'foo*') ; do
printf 'File found: %s\n' "$file"
done
}
এটি এখনও ব্যর্থ হবে যদি ফাইলের নামগুলিতে আক্ষরিক নতুন লাইন থাকে তবে স্থানগুলি এটি ভাঙবে না।
তবে আইএফএসের সাথে জগাখিচির প্রয়োজন নেই। এটি করার জন্য আমার পছন্দের উপায়টি এখানে:
getlist() {
while IFS= read -d $'\0' -r file ; do
printf 'File found: %s\n' "$file"
done < <(find . -iname 'foo*' -print0)
}
আপনি যদি < <(command)
সিনট্যাক্সটি অপরিচিত দেখতে পান তবে আপনার প্রক্রিয়া প্রতিস্থাপন সম্পর্কে পড়া উচিত । এই ওভারের সুবিধা for file in $(find ...)
হ'ল স্পেস, নিউলাইন এবং অন্যান্য অক্ষর সহ ফাইলগুলি সঠিকভাবে পরিচালনা করা হয়। এই কাজ করে কারণ find
সঙ্গে -print0
একটি ব্যবহার করা হবে null
(ওরফে \0
সম্পর্কে newline অসদৃশ প্রতিটি ফাইল নামের জন্য টারমিনেটর হিসাবে) এবং,, নাল একটি ফাইল নামে একটি আইনি চরিত্র নয়।
প্রায় সমতুল্য সংস্করণে এটির সুবিধা
getlist() {
find . -iname 'foo*' -print0 | while read -d $'\0' -r file ; do
printf 'File found: %s\n' "$file"
done
}
লুপটি সংরক্ষণের সময় এটির শরীরে কোনও পরিবর্তনশীল কাজ রয়েছে। এটি হ'ল যদি আপনি while
উপরের দিকে পাইপ করেন তবে এর শরীরটি while
একটি সাবশেলে রয়েছে যা আপনি যা চান তা নাও হতে পারে।
প্রক্রিয়া প্রতিস্থাপন সংস্করণ ওভারের সুবিধাটি find ... -print0 | xargs -0
ন্যূনতম: xargs
সংস্করণটি ঠিক আছে যদি আপনার প্রয়োজন হয় তবে একটি লাইন মুদ্রণ করুন বা ফাইলে একটি একক ক্রিয়াকলাপ করা প্রয়োজন, তবে আপনাকে যদি একাধিক পদক্ষেপের প্রয়োজন হয় তবে লুপ সংস্করণটি সহজ।
সম্পাদনা : এখানে একটি দুর্দান্ত পরীক্ষার স্ক্রিপ্ট রয়েছে যাতে আপনি এই সমস্যাটি সমাধান করার ক্ষেত্রে বিভিন্ন চেষ্টার মধ্যে পার্থক্য সম্পর্কে ধারণা পেতে পারেন
#!/usr/bin/env bash
dir=/tmp/getlist.test/
mkdir -p "$dir"
cd "$dir"
touch 'file not starting foo' foo foobar barfoo 'foo with spaces'\
'foo with'$'\n'newline 'foo with trailing whitespace '
# while with process substitution, null terminated, empty IFS
getlist0() {
while IFS= read -d $'\0' -r file ; do
printf 'File found: '"'%s'"'\n' "$file"
done < <(find . -iname 'foo*' -print0)
}
# while with process substitution, null terminated, default IFS
getlist1() {
while read -d $'\0' -r file ; do
printf 'File found: '"'%s'"'\n' "$file"
done < <(find . -iname 'foo*' -print0)
}
# pipe to while, newline terminated
getlist2() {
find . -iname 'foo*' | while read -r file ; do
printf 'File found: '"'%s'"'\n' "$file"
done
}
# pipe to while, null terminated
getlist3() {
find . -iname 'foo*' -print0 | while read -d $'\0' -r file ; do
printf 'File found: '"'%s'"'\n' "$file"
done
}
# for loop over subshell results, newline terminated, default IFS
getlist4() {
for file in "$(find . -iname 'foo*')" ; do
printf 'File found: '"'%s'"'\n' "$file"
done
}
# for loop over subshell results, newline terminated, newline IFS
getlist5() {
IFS=$'\n'
for file in $(find . -iname 'foo*') ; do
printf 'File found: '"'%s'"'\n' "$file"
done
}
# see how they run
for n in {0..5} ; do
printf '\n\ngetlist%d:\n' $n
eval getlist$n
done
rm -rf "$dir"