300のデータファイルを保持するディレクトリがあるとします。これらのファイルを200個ランダムに選択して、別のディレクトリに移動したいと思います。 Unix/Linuxでそれを行う方法はありますか?
システムに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
ケビンのソリューションは素晴らしい働きをします!頭の上から覚える方が簡単だと思うので、私が頻繁に使用した他のものは次のようなものです。
cp `ls | shuf -n 200` destination
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
これは重複を選択しますisしない 空白などのファイル名でテストされています。
重複を回避する最も簡単な方法は、すべてのファイルを反復処理し、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 % ${#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)
Bashの1つのライナー:
ls original_directory/|sort -R|head -number_of_files_to_move|while read file; do cp "new_directory/"$file test; done