ডিরেক্টরিতে ফাইলগুলির মাধ্যমে পুনরাবৃত্তভাবে পুনরাবৃত্তি করুন


15

ডিরেক্টরিতে ফাইলগুলির মাধ্যমে পুনরাবৃত্তভাবে পুনরাবৃত্তি সহজেই এর মাধ্যমে করা যেতে পারে:

find . -type f -exec bar {} \;

তবে উপরেরগুলি আরও জটিল জিনিসের জন্য কাজ করে না, যেখানে প্রচুর শর্তাধীন শাখা, লুপিং করা দরকার। আমি উপরের জন্য এটি ব্যবহার করতাম:

while read line; do [...]; done < <(find . -type f)

তবে মনে হচ্ছে এটি অস্পষ্ট অক্ষরযুক্ত ফাইলগুলির জন্য কাজ করে না:

$ touch $'a\nb'
$ find . -type f
./a?b

এমন কোনও বিকল্প আছে যা এই ধরণের অস্পষ্ট চরিত্রগুলি ভালভাবে পরিচালনা করে?


1
find ... -exec bash -c 'echo filename is in \$0: "$0"' {} \;এটি করার একটি ভাল উপায়।
jw013

আপনি এটি সমাধান করতে পারেন এবং নিজের আসল নকশাটি এতে পরিবর্তন করে রাখতে read lineপারেন IFS= read -r line। কেবলমাত্র অক্ষরটি এটি ভেঙে দেবে এটি একটি নতুন লাইন।
প্যাট্রিক

1
@ পেট্রিক, তবে ফাইলের নামগুলিতে নতুন লাইন থাকতে পারে। এজন্যই -d $'\0'পছন্দনীয়।
গডলিজিক

উত্তর:


7

নিরাপদfind জন্য এখনও অন্য ব্যবহার :

while IFS= read -r -d '' -u 9
do
    [Do something with "$REPLY"]
done 9< <( find . -type f -exec printf '%s\0' {} + )

(এটি কোনও পসিক্সের সাথে কাজ করে findতবে শেল অংশটির জন্য ব্যাশ প্রয়োজন * * BSD এবং GNU সন্ধানের -print0পরিবর্তে আপনি এর পরিবর্তে ব্যবহার করতে পারেন -exec printf '%s\0' {} +, এটি কিছুটা দ্রুত হবে))

এটি লুপের মধ্যে স্ট্যান্ডার্ড ইনপুট ব্যবহার করা সম্ভব করে এবং এটি যে কোনও পথ দিয়ে কাজ করে।


1
কারণ আমাকে এটি সন্ধান করতে হয়েছিল: "পড়ুন ... কোনও নাম সরবরাহ না করা থাকলে, পঠন করা লাইনটি পরিবর্তনশীল REPLY এ নির্ধারিত হয়।" সুতরাংdo echo "Filename is '$REPLY'"
অ্যান্ড্রু

9

এটি করা যেমন সহজ:

find -exec sh -c 'inline script "$0"' {} \;

অথবা ...

find -exec executable_script {} \;

5

সবচেয়ে সহজ (এখনও নিরাপদ) পদ্ধতির মধ্যে শেল গ্লোববিং ব্যবহার করা হয়:

$ for f in *; do printf ":%s:\n" "$f"; done 
:a b:
:c
d:
:-e:
:e  f:
h:

উপ-ডিরেক্টরিগুলিতে উপরের পুনরাবৃত্তি করতে (ব্যাশে), আপনি globstarবিকল্পটি ব্যবহার করতে পারেন ; dotglobযার নাম দিয়ে শুরু হয় এমন ফাইলগুলিও মেলতে সেট করেছে .:

$ shopt -s globstar dotglob
$ for f in **/*; do printf ":%s:\n" "$f"; done 
:a b:
:c
d:
:-e:
:e  f:
:foo:
:foo/file1:
:foo/file two:
h:

সাবধান থাকুন যে 4.2 বাশ পর্যন্ত, **/ডিরেক্টরিগুলিতে প্রতীকী লিঙ্কগুলিতে পুনরাবৃত্তি হয়। যেহেতু বাশ 4.3, **/কেবলমাত্র ডিরেক্টরিতে পুনরাবৃত্তি করে find

আর একটি সাধারণ সমাধান এর সাথে ব্যবহার find -print0করা xargs -0:

$ touch -- 'a b' $'c\nd' $'e\tf' $'g\rh' '-e'
$ find . -type f -print0 | xargs -0 -I{} printf ":%s:\n" {}
h:/g
:./e    f:
:./a b:
:./-e:
:./c
d:

নোট করুন যে h:/gফাইলের নামটিতে একটি রয়েছে তাই প্রকৃতপক্ষে সঠিক \r


4

আপনার পঠন লুপটি বহনযোগ্যভাবে করা কিছুটা কঠিন, তবে বিশেষত ব্যাশের জন্য আপনি এই জাতীয় কিছু চেষ্টা করতে পারেন

প্রাসঙ্গিক অংশ:

while IFS= read -d $'\0' -r file ; do
        printf 'File found: %s\n' "$file"
done < <(find . -iname 'foo*' -print0)

এটি findNU টি অক্ষর (0x00) দ্বারা সীমিত তার আউটপুট প্রিন্ট readকরার জন্য এবং NUL- সীমাবদ্ধ রেখাগুলি আনার জন্য নির্দেশ দেয় ( -d $'\0'ব্যাকস্ল্যাশগুলি অন্যান্য অক্ষরের ( -r)) এর জন্য পলায়ন হিসাবে পরিচালনা না করে এবং ( IFS=) লাইনগুলিতে বিভক্ত কোনও শব্দ না করে । যেহেতু 0x00 একটি বাইট যা ইউনিক্সের ফাইলনাম বা পাথগুলিতে ঘটতে পারে না তাই এটি আপনার সমস্ত অদ্ভুত ফাইলনাম সমস্যাগুলি পরিচালনা করতে পারে handle


1
-d ''সমতূল্য -d $'\0'
l0b0
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.