300個のデータファイルを保持するディレクトリがあるとします。これらのファイルのうち200個をランダムに選択し、別のディレクトリに移動したいです。Unix / Linuxでそれを行う方法はありますか?
shuf
、head
(または単に使用してshuf -n
、マニュアルページを読むべきです...)
300個のデータファイルを保持するディレクトリがあるとします。これらのファイルのうち200個をランダムに選択し、別のディレクトリに移動したいです。Unix / Linuxでそれを行う方法はありますか?
shuf
、head
(または単に使用してshuf -n
、マニュアルページを読むべきです...)
回答:
システムにがある場合、shuf
これを非常に便利に使用できます((いファイル名を処理する場合でも)。
shuf -zen200 source/* | xargs -0 mv -t dest
あなたshuf
が持っていないが、sort
そのを持っている場合-R
、これはうまくいくはずです:
find source -type f -print0 | sort -Rz | cut -d $'\0' -f-200 | xargs -0 mv -t dest
shuf
呼び出されませんtros
。)
files=(*)
for (( i=0; i<200; i++ )); do
keys=("${!files[@]}")
rnd=$(( RANDOM % ${#keys[@]} ))
key=${keys[$rnd]}
mv "${files[$key]}" "$otherdir"
unset files[$key]
done
すべてのファイル名をbashの「files」という名前の配列に入れます。
files=( * )
配列のサイズ:
echo ${#files[@]}
それらの2/3をサンプルサイズとして定義します。
take=$((2*${#files[@]}/3))
for i in $(seq 1 $take)
do
r=$((RANDOM%${#files[@]}))
echo ${files[r]}
done
これは、重複を選択します、とされていない空白やなとファイル名を使用してテスト。
重複を避けるための最も簡単な方法は、すべてのファイルを反復処理し、2/3のチャンスで各ファイルを選択することですが、これは必ずしも200ファイルになるとは限りません。
これは、リストから選択されたファイルを削除し、要件を満たします。
#!/bin/bash
files=( * )
# define 2/3 of them as sample size:
take=$((2*${#files[@]}/3))
while (( i < $take ))
do
r=$((RANDOM%${#files[@]}))
f=${files[r]}
if [[ -n $f ]]
then
i=$((i+1))
echo ${files[r]}
unset files[r]
fi
done
$RANDOM
値は0〜32767 のみであるため、32768を超えるファイルがある場合、これは正しく機能しません。また、フェッチは最初のファイルに偏っています。
これを統計的にランダムにする必要がある場合は、使用しないでくださいRANDOM % ${#keys[@]}
。考慮してください:
$RANDOM
32768の一意の値がありますしたがって、最初のアイテムを選択すると、68個の最初の要素のそれぞれについて110/32768〜= 0.33569%の確率があり、他の232個の要素のそれぞれについて109/32768〜= 0.33264%の確率が選択されます。ピッキングはさまざまな機会で何度か繰り返され32768 % ${#keys[@]} -ne 0
ますが、の場合は常に最初の要素にバイアスがかけられるため、エラーが悪化します。
これは公平である必要があり、任意のファイル名で動作します:
while IFS= read -r -d '' -u 9
do
mv -- "$REPLY" /target/dir
done 9< <(find /source/dir -mindepth 1 -print0 | shuf -n 200 -z)
list.files()
ます