এই উত্তরের যে কোনও ধরণের ফাইলের সমাধান রয়েছে । নতুন লাইন বা স্পেস সহ।
সাম্প্রতিক ব্যাশের পাশাপাশি প্রাচীন বাশ এমনকি পুরানো পোস্টিক্স শেলগুলির সমাধান রয়েছে solutions
এই উত্তরে নীচে তালিকাভুক্ত গাছ [1] পরীক্ষার জন্য ব্যবহৃত হয়।
নির্বাচন করা
select
কোনও অ্যারে দিয়ে কাজ করা সহজ :
$ dir='deep/inside/a/dir'
$ arr=( "$dir"/* )
$ select var in "${arr[@]}"; do echo "$var"; break; done
অথবা অবস্থানগত পরামিতি সহ:
$ set -- "$dir"/*
$ select var; do echo "$var"; break; done
সুতরাং, একমাত্র আসল সমস্যাটি হ'ল একটি ফাইলের তালিকা বা অবস্থানের প্যারামিটারের ভিতরে "ফাইলগুলির তালিকা" (সঠিকভাবে সীমিত)। পড়তে থাকুন।
সজোরে আঘাত
বাশ দিয়ে আপনি যে সমস্যাটি প্রতিবেদন করেছেন তা আমি দেখতে পাচ্ছি না। বাশ একটি প্রদত্ত ডিরেক্টরিতে অনুসন্ধান করতে সক্ষম:
$ dir='deep/inside/a/dir'
$ printf '<%s>\n' "$dir"/*
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
অথবা, আপনি যদি একটি লুপ পছন্দ করেন:
$ set -- "$dir"/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
নোট করুন যে উপরের সিনট্যাক্সটি কোনও (যুক্তিসঙ্গত) শেল (কমপক্ষে সিএস নয়) দিয়ে সঠিকভাবে কাজ করবে।
উপরের সিনট্যাক্সের একমাত্র সীমাটি অন্যান্য ডিরেক্টরিতে নেমে আসা।
তবে বাশ তা করতে পারে:
$ shopt -s globstar
$ set -- "$dir"/**/*
$ for f; do printf '<%s>\n' "$f"; done
<deep/inside/a/dir/directory>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/zz last file>
কেবলমাত্র কিছু ফাইল নির্বাচন করতে (ফাইলগুলির মধ্যে শেষ হওয়া ফাইলগুলির মতো) কেবল * প্রতিস্থাপন করুন:
$ set -- "$dir"/**/*file
$ printf '<%s>\n' "$@"
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/directory/zz last file>
<deep/inside/a/dir/file>
<deep/inside/a/dir/zz last file>
বলিষ্ঠ
আপনি যখন শিরোনামে একটি "স্পেস- সেফ " রাখবেন, আমি ধরে নিতে যাচ্ছি আপনি যা বোঝাতে চেয়েছিলেন তা " শক্ত " ছিল।
স্পেসগুলি (বা নিউলাইনস) সম্পর্কে শক্তিশালী হওয়ার সহজ উপায় হ'ল ফাঁকা স্থান (বা নিউলাইন) থাকা ইনপুটটির প্রক্রিয়াকরণটিকে প্রত্যাখ্যান করা। শেলটিতে এটি করার একটি খুব সহজ উপায় হ'ল কোনও স্থানের সাথে কোনও ফাইলের নাম প্রসারিত হলে কোনও ত্রুটি সহ প্রস্থান করা। এটি করার বিভিন্ন উপায় রয়েছে তবে সর্বাধিক কমপ্যাক্ট (এবং পিক্সিক্স) (তবে একটি ডিরেক্টরি সামগ্রীর মধ্যে স্যুডডাইরেক্টরিজের নাম এবং ডট-ফাইলগুলি এড়ানো সহ সীমাবদ্ধ) হ'ল:
$ set -- "$dir"/file* # read the directory
$ a="$(printf '%s' "$@" x)" # make it a long string
$ [ "$a" = "${a%% *}" ] || echo "exit on space" # if $a has an space.
$ nl='
' # define a new line in the usual posix way.
$ [ "$a" = "${a%%"$nl"*}" ] || echo "exit on newline" # if $a has a newline.
যদি ব্যবহৃত সমাধানটি সেই আইটেমগুলির মধ্যে কোনওর মধ্যে শক্ত হয় তবে পরীক্ষাটি সরিয়ে ফেলুন।
ব্যাশে, উপ-ডিরেক্টরিগুলি উপরে বর্ণিত ** দিয়ে একবারে পরীক্ষা করা যেতে পারে।
ডট ফাইল অন্তর্ভুক্ত করার কয়েকটি উপায় রয়েছে, পসিক্স সমাধানটি হ'ল:
set -- "$dir"/* "$dir"/.[!.]* "$dir"/..?*
অনুসন্ধান
যদি কোনও কারণে অবশ্যই ব্যবহার করা হয় তবে ডিলিমিটারটি একটি NUL (0x00) দিয়ে প্রতিস্থাপন করুন।
bash 4.4+
$ readarray -t -d '' arr < <(find "$dir" -type f -name file\* -print0)
$ printf '<%s>\n' "${arr[@]}"
<deep/inside/a/dir/file name>
<deep/inside/a/dir/file with a
newline>
<deep/inside/a/dir/directory/file name>
<deep/inside/a/dir/directory/file with a
newline>
<deep/inside/a/dir/directory/file>
<deep/inside/a/dir/file>
bash 2.05+
i=1 # lets start on 1 so it works also in zsh.
while IFS='' read -d '' val; do
arr[i++]="$val";
done < <(find "$dir" -type f -name \*file -print0)
printf '<%s>\n' "${arr[@]}"
POSIXLY
একটি বৈধ পসিক্স সমাধান তৈরি করতে যেখানে সন্ধানের কোনও NUL ডিলিমিটার নেই এবং পাঠের জন্য কোনও নেই -d
(না -a
) আমাদের সম্পূর্ণ ডিফেরেন্ট অ্যাপ্রোচ দরকার।
-exec
শেল থেকে একটি কল সহ আমাদের খুঁজে পেতে একটি জটিল ব্যবহার করতে হবে :
find "$dir" -type f -exec sh -c '
for f do
echo "<$f>"
done
' sh {} +
বা, যা প্রয়োজন তা যদি একটি নির্বাচন হয় (নির্বাচন করা বাশের অংশ হয় তবে শ নয়):
$ find "$dir" -type f -exec bash -c '
select f; do echo "<$f>"; break; done ' bash {} +
1) deep/inside/a/dir/file name
2) deep/inside/a/dir/zz last file
3) deep/inside/a/dir/file with a
newline
4) deep/inside/a/dir/directory/file name
5) deep/inside/a/dir/directory/zz last file
6) deep/inside/a/dir/directory/file with a
newline
7) deep/inside/a/dir/directory/file
8) deep/inside/a/dir/file
#? 3
<deep/inside/a/dir/file with a
newline>
[1] এই গাছটি (012 ডলার নতুন লাইনগুলি):
$ tree
.
└── deep
└── inside
└── a
└── dir
├── directory
│ ├── file
│ ├── file name
│ └── file with a \012newline
├── file
├── file name
├── otherfile
├── with a\012newline
└── zz last file
এই দুটি কমান্ড দিয়ে নির্মিত হতে পারে:
$ mkdir -p deep/inside/a/dir/directory/
$ touch deep/inside/a/dir/{,directory/}{file{,\ {name,with\ a$'\n'newline}},zz\ last\ file}