আমার প্রায় 2000 টি ফাইল সহ একটি ডিরেক্টরি রয়েছে। N
বাশ স্ক্রিপ্ট বা পাইপড কমান্ডের একটি তালিকা ব্যবহার করে আমি কীভাবে ফাইলগুলির এলোমেলো নমুনা নির্বাচন করতে পারি ?
ls | shuf -n 5
ইউনিক্স স্ট্যাকেক্সচেঞ্জের উত্স
আমার প্রায় 2000 টি ফাইল সহ একটি ডিরেক্টরি রয়েছে। N
বাশ স্ক্রিপ্ট বা পাইপড কমান্ডের একটি তালিকা ব্যবহার করে আমি কীভাবে ফাইলগুলির এলোমেলো নমুনা নির্বাচন করতে পারি ?
ls | shuf -n 5
ইউনিক্স স্ট্যাকেক্সচেঞ্জের উত্স
উত্তর:
এখানে একটি স্ক্রিপ্ট যা GNU সাজ্টের র্যান্ডম বিকল্প ব্যবহার করে:
ls |sort -R |tail -$N |while read file; do
# Something involving $file, or you can leave
# off the while to just get the filenames
done
"$file"
প্রদর্শিত, প্রদর্শিত না ব্যবহারের জন্য স্পেসগুলি সংবেদনশীল হবে।
আপনি তার জন্য shuf
(জিএনইউ কোর্টিল প্যাকেজ থেকে) ব্যবহার করতে পারেন। কেবল এটিকে ফাইলের নামের একটি তালিকা খাওয়ান এবং এলোমেলো ক্রমানুসারে প্রথম লাইনে ফিরে আসতে বলুন:
ls dirname | shuf -n 1
# probably faster and more flexible:
find dirname -type f | shuf -n 1
# etc..
-n, --head-count=COUNT
পছন্দসই লাইনের সংখ্যা ফেরতের জন্য মানটি সামঞ্জস্য করুন । উদাহরণস্বরূপ 5 টি র্যান্ডম ফাইল নামগুলি আপনি ব্যবহার করবেন:
find dirname -type f | shuf -n 5
N
র্যান্ডম ফাইলগুলি নির্বাচন করতে চেয়েছিল , তাই ব্যবহার 1
করা কিছুটা বিভ্রান্তিকর।
find dirname -type f -print0 | shuf -zn1
এখানে কয়েকটি সম্ভাবনা রয়েছে যা আউটপুটকে বিশ্লেষণ করে না ls
এবং এটি তাদের নামে স্পেস এবং মজার চিহ্ন সহ ফাইলগুলি সম্পর্কিত 100% নিরাপদ। এগুলির সবগুলি randf
এলোমেলো ফাইলগুলির একটি তালিকা সহ একটি অ্যারে তৈরি করবে । এই অ্যারে printf '%s\n' "${randf[@]}"
প্রয়োজনে সহজেই মুদ্রিত হয় ।
এটি সম্ভবত একই ফাইলটিকে বেশ কয়েকবার আউটপুট দেবে N
এবং আগে থেকেই জানা দরকার। এখানে আমি এন = 42 বেছে নিয়েছি।
a=( * )
randf=( "${a[RANDOM%${#a[@]}]"{1..42}"}" )
এই বৈশিষ্ট্যটি খুব ভাল নথিভুক্ত নয়।
এন যদি আগে থেকে জানা না যায় তবে আপনি আগের সম্ভাবনাটি পছন্দ করেছেন, আপনি ব্যবহার করতে পারেন eval
। তবে এটি মন্দ, এবং অবশ্যই আপনাকে অবশ্যই নিশ্চিত করতে হবে যে N
ভালভাবে পরীক্ষা না করে সরাসরি ব্যবহারকারী ইনপুট থেকে আসে না!
N=42
a=( * )
eval randf=( \"\${a[RANDOM%\${#a[@]}]\"\{1..$N\}\"}\" )
আমি ব্যক্তিগতভাবে অপছন্দ করি eval
এবং তাই এই উত্তর!
আরও সরল পদ্ধতি (লুপ) ব্যবহার করে একই:
N=42
a=( * )
randf=()
for((i=0;i<N;++i)); do
randf+=( "${a[RANDOM%${#a[@]}]}" )
done
আপনি যদি একই ফাইলটি কয়েকবার সম্ভবত না চান:
N=42
a=( * )
randf=()
for((i=0;i<N && ${#a[@]};++i)); do
((j=RANDOM%${#a[@]}))
randf+=( "${a[j]}" )
a=( "${a[@]:0:j}" "${a[@]:j+1}" )
done
নোট । এটি একটি পুরানো পোস্টের দেরী উত্তর, তবে গৃহীত উত্তরগুলি একটি বাহ্যিক পৃষ্ঠায় লিঙ্ক করে যা ভয়ঙ্কর দেখায়সজোরে আঘাতঅনুশীলন করুন, এবং অন্য উত্তরটি আরও ভাল নয় কারণ এটি এর আউটপুটকেও বিশ্লেষণ করে ls
। গৃহীত উত্তরের একটি মন্তব্য লুনাথের একটি দুর্দান্ত উত্তরের দিকে ইঙ্গিত করে যা স্পষ্টতই ভাল অনুশীলন দেখায়, তবে ঠিক ওপিকে উত্তর দেয় না।
"{1..42}"
অংশটি পিছনে রেখে পছন্দ করে নি "1"
। এছাড়াও, $RANDOM
শুধুমাত্র 15 বিট এবং পদ্ধতিটি 32767 টিরও বেশি ফাইল থেকে পছন্দ করে কাজ করবে না।
ls | shuf -n 10 # ten random files
ls
। উদাহরণস্বরূপ যদি কোনও ফাইলনামে নতুন লাইন থাকে তবে এটি কাজ করবে না।
ls
আপনাকে "পরিষ্কার" ফাইলের নাম দেওয়ার গ্যারান্টি নেই যাতে আপনার পিরিয়ডের উপর নির্ভর করা উচিত নয়। এই বিষয়গুলি বিরল বা অস্বাভাবিক এই বিষয়টি সমস্যাটি পরিবর্তন করে না; বিশেষত প্রদত্ত এর জন্য আরও ভাল সমাধান রয়েছে।
ls
ডিরেক্টরি এবং ফাঁকা লাইন অন্তর্ভুক্ত থাকতে পারে। আমি find . -type f | shuf -n10
পরিবর্তে এর মতো কিছু প্রস্তাব করব ।
এলএস পার্স করা এড়াতে5
এলোমেলো ফাইল নির্বাচন করার জন্য একটি সহজ সমাধান । এটি স্পেস, নিউলাইন এবং অন্যান্য বিশেষ অক্ষরযুক্ত ফাইলগুলির সাথেও কাজ করে:
shuf -ezn 5 * | xargs -0 -n1 echo
echo
আপনি যে ফাইলগুলি ফাইলের জন্য কার্যকর করতে চান তা দিয়ে প্রতিস্থাপন করুন ।
read
পার্সিংয়ের মতো একই সমস্যা নেই ls
? যথা, এটি লাইনে এক এক করে পড়ে, সুতরাং এটি তাদের নামে নতুন লাইনের ফাইলগুলির জন্য কাজ করে না
যদি আপনি পাইথন ইনস্টল করেন (পাইথন 2 বা পাইথন 3 এর সাথে কাজ করে):
একটি ফাইল নির্বাচন করতে (বা একটি স্বেচ্ছাচারিত কমান্ড থেকে লাইন), ব্যবহার করুন
ls -1 | python -c "import sys; import random; print(random.choice(sys.stdin.readlines()).rstrip())"
N
ফাইল / লাইন নির্বাচন করতে, ব্যবহার করুন (নোটটি N
কমান্ডের শেষে রয়েছে, এটি একটি সংখ্যার মাধ্যমে প্রতিস্থাপন করুন)
ls -1 | python -c "import sys; import random; print(''.join(random.sample(sys.stdin.readlines(), int(sys.argv[1]))).rstrip())" N
এটি @ gniourf_gniourf এর দেরী জবাবের পরে একটি প্রতিক্রিয়া, যা আমি সবেমাত্র উচ্চারণ করেছি কারণ এটি দ্বিগুণ হয়ে এখন পর্যন্ত সেরা উত্তর। (একবার এড়ানোর জন্য eval
এবং একবার নিরাপদ ফাইল নাম হ্যান্ডলিংয়ের জন্য))
তবে এই উত্তরটি "খুব ভাল ডকুমেন্টেড নয়" বৈশিষ্ট্য (গুলি) আনট্যাগল করতে কয়েক মিনিট সময় নিয়েছে। আপনার বাশ দক্ষতা যদি যথেষ্ট শক্ত হয় তবে আপনি কীভাবে এটি কাজ করে তা তাত্ক্ষণিকভাবে দেখেছিলেন, তবে এই মন্তব্যটি এড়িয়ে যান। তবে আমি তা করি নি, এবং এটির শৃঙ্খলাবদ্ধ না করে আমি মনে করি এটি ব্যাখ্যা করার উপযুক্ত।
বৈশিষ্ট্য # 1 হ'ল শেলের নিজস্ব ফাইল গ্লোববিং। a=(*)
একটি অ্যারে তৈরি করে $a
, যার সদস্যরা বর্তমান ডিরেক্টরিতে থাকা ফাইলগুলি। ফাইল ফাইলের সমস্ত অদ্ভুততা বোঝে বাশ, সুতরাং সেই তালিকাটি সঠিক, নিশ্চিত পলায়নের গ্যারান্টিযুক্ত, ইত্যাদি পাঠ্য ফাইলের নামগুলি সঠিকভাবে পার্স করার বিষয়ে চিন্তা করার দরকার নেই ls
।
বৈশিষ্ট্য # 2 হ'ল অ্যারেগুলির জন্য বাশ প্যারামিটার বিস্তৃতি , যার মধ্যে একটির অন্যের মধ্যে বাসা বাঁধে। এটি দিয়ে শুরু হয় , যা দৈর্ঘ্যে প্রসারিত হয় ।${#ARRAY[@]}
$ARRAY
সেই সম্প্রসারণটি অ্যারে সাবস্ক্রিপ্ট করার জন্য ব্যবহৃত হয়। 1 এবং N এর মধ্যে একটি এলোমেলো সংখ্যা খুঁজে পাওয়ার মানক উপায়টি হল র্যান্ডম সংখ্যার মডুলো এন এর মান নেওয়া take আমরা 0 এবং আমাদের অ্যারের দৈর্ঘ্যের মধ্যে একটি এলোমেলো সংখ্যা চাই। স্পষ্টতার জন্য দুটি পংক্তিতে বিভক্ত পদ্ধতিটি এখানে:
LENGTH=${#ARRAY[@]}
RANDOM=${a[RANDOM%$LENGTH]}
কিন্তু এই সমাধানটি এটি একটি একক লাইনে করে, অপ্রয়োজনীয় ভেরিয়েবল অ্যাসাইনমেন্টটি সরিয়ে দেয়।
বৈশিষ্ট্য # 3 হ'ল ব্যাশ বন্ধনী সম্প্রসারণ , যদিও আমাকে স্বীকার করতে হবে আমি এটি পুরোপুরি বুঝতে পারি না। বন্ধনী সম্প্রসারণ উদাহরণস্বরূপ ব্যবহার করা হয়, 25 নামে ফাইলগুলির একটি তালিকা তৈরি করতে filename1.txt
, filename2.txt
ইত্যাদি: echo "filename"{1..25}".txt"
।
উপরের সাবশেলের অভ্যন্তরের অভিব্যক্তি "${a[RANDOM%${#a[@]}]"{1..42}"}"
, 42 টি পৃথক বিস্তৃতি তৈরি করতে সেই কৌশলটি ব্যবহার করে। ধনুর্বন্ধনী প্রসারণটি এবং এর মধ্যে একক অঙ্ক ]
রাখে }
, যা প্রথমে আমি ভেবেছিলাম অ্যারে সাবস্ক্রিপশন করছিলাম, তবে যদি তা হয় তবে এটির আগে একটি কোলন থাকবে। (এটি অ্যারেতে এলোমেলো জায়গা থেকে একটানা 42 টি আইটেম ফিরে আসত, যা অ্যারে থেকে 42 টি এলোমেলো আইটেম ফেরত দেওয়ার মত নয়) আমি মনে করি এটি শেলটি 42 বার প্রসারিত করে চলেছে, এরপরে ফিরে আসবে অ্যারে থেকে 42 এলোমেলো আইটেম। (তবে কেউ যদি আরও পুরোপুরি ব্যাখ্যা করতে পারে তবে আমি এটি শুনতে পছন্দ করব))
N কে হার্ডকোডিং (42 থেকে 42) করার কারণ হ'ল চলক প্রসারণের আগে ব্রেস সম্প্রসারণ ঘটে।
পরিশেষে, আপনি যদি একটি ডিরেক্টরি শ্রেণিবিন্যাসের জন্য এটি পুনরাবৃত্তভাবে করতে চান তবে এখানে ফিচার # 4 's
shopt -s globstar
a=( ** )
এটি শেল বিকল্পটি সক্রিয় করে যা **
পুনরাবৃত্তির সাথে মেলে। এখন আপনার $a
অ্যারেতে সম্পূর্ণ শ্রেণিবিন্যাসের প্রতিটি ফাইল রয়েছে।
আপনার ফোল্ডারে যদি আরও ফাইল থাকে তবে আপনি ইউনিক্স স্ট্যাকেক্সচেঞ্জে পাওয়া নীচের পাইপযুক্ত কমান্ডটি ব্যবহার করতে পারেন ।
find /some/dir/ -type f -print0 | xargs -0 shuf -e -n 8 -z | xargs -0 cp -vt /target/dir/
এখানে আমি ফাইল কপি করতে চেয়েছিলেন, কিন্তু যদি আপনি ফাইল স্থানান্তর করতে চান বা কিছু অন্য না, শুধু গত কমান্ড আমি কোথায় ব্যবহার করেছেন পরিবর্তন cp
।
এই একমাত্র স্ক্রিপ্ট আমি ম্যাকওএসে ব্যাশ দিয়ে সুন্দর খেলতে পারি। আমি নিম্নলিখিত দুটি লিঙ্ক থেকে স্নিপেট একত্রিত এবং সম্পাদনা করেছি:
ls কমান্ড: আমি প্রতি ফাইলটিতে একটি পুনরাবৃত্ত পূর্ণ-পাথ তালিকা পেতে পারি?
#!/bin/bash
# Reads a given directory and picks a random file.
# The directory you want to use. You could use "$1" instead if you
# wanted to parametrize it.
DIR="/path/to/"
# DIR="$1"
# Internal Field Separator set to newline, so file names with
# spaces do not break our script.
IFS='
'
if [[ -d "${DIR}" ]]
then
# Runs ls on the given dir, and dumps the output into a matrix,
# it uses the new lines character as a field delimiter, as explained above.
# file_matrix=($(ls -LR "${DIR}"))
file_matrix=($(ls -R $DIR | awk '; /:$/&&f{s=$0;f=0}; /:$/&&!f{sub(/:$/,"");s=$0;f=1;next}; NF&&f{ print s"/"$0 }'))
num_files=${#file_matrix[*]}
# This is the command you want to run on a random file.
# Change "ls -l" by anything you want, it's just an example.
ls -l "${file_matrix[$((RANDOM%num_files))]}"
fi
exit 0
ম্যাকোস-এর মধ্যে বাছাই -R এবং shuf কমান্ড নেই, সুতরাং আমার একটি বাশ কেবলমাত্র সমাধান দরকার যা ডুপ্লিকেট ছাড়াই সমস্ত ফাইলকে এলোমেলো করে তোলে এবং এটি এখানে খুঁজে পায় না। এই সমাধানটি gniourf_gniourf এর সমাধান # 4 এর মতো, তবে আশা করি আরও ভাল মন্তব্য যুক্ত করুন।
স্ক্রিপ্টটি যদি এন এর সাথে একটি কাউন্টার ব্যবহার করে এন নমুনাগুলির পরে থামার জন্য পরিবর্তন করা সহজ হয় বা জি।
#!/bin/bash
array=(*) # this is the array of files to shuffle
# echo ${array[@]}
for dummy in "${array[@]}"; do # do loop length(array) times; once for each file
length=${#array[@]}
randomi=$(( $RANDOM % $length )) # select a random index
filename=${array[$randomi]}
echo "Processing: '$filename'" # do something with the file
unset -v "array[$randomi]" # set the element at index $randomi to NULL
array=("${array[@]}") # remove NULL elements introduced by unset; copy array
done
আমি এটি ব্যবহার করি: এটি অস্থায়ী ফাইল ব্যবহার করে তবে একটি ডিরেক্টরিতে গভীরভাবে যায় যতক্ষণ না এটি একটি নিয়মিত ফাইল খুঁজে পায় এবং এটি ফিরে না আসে।
# find for a quasi-random file in a directory tree:
# directory to start search from:
ROOT="/";
tmp=/tmp/mytempfile
TARGET="$ROOT"
FILE="";
n=
r=
while [ -e "$TARGET" ]; do
TARGET="$(readlink -f "${TARGET}/$FILE")" ;
if [ -d "$TARGET" ]; then
ls -1 "$TARGET" 2> /dev/null > $tmp || break;
n=$(cat $tmp | wc -l);
if [ $n != 0 ]; then
FILE=$(shuf -n 1 $tmp)
# or if you dont have/want to use shuf:
# r=$(($RANDOM % $n)) ;
# FILE=$(tail -n +$(( $r + 1 )) $tmp | head -n 1);
fi ;
else
if [ -f "$TARGET" ] ; then
rm -f $tmp
echo $TARGET
break;
else
# is not a regular file, restart:
TARGET="$ROOT"
FILE=""
fi
fi
done;
মিঃ কাংয়ের কাছ থেকে সামান্য ডক্টার্ড করা পার্ল সমাধান সম্পর্কে কীভাবে: ইউনিক্স কমান্ড লাইনে বা শেল স্ক্রিপ্টে আমি কোনও টেক্সট ফাইলের লাইনগুলি কীভাবে বদলাতে
পারি?
s ls | perl -MList :: Util = shuffle -e '@lines = shuffle (<>); @ লাইনগুলি প্রিন্ট করুন [0..4] '