web-dev-qa-db-ja.com

ファイルのコレクションからランダムなサンプルを収集する最良の方法

300のデータファイルを保持するディレクトリがあるとします。これらのファイルを200個ランダムに選択して、別のディレクトリに移動したいと思います。 Unix/Linuxでそれを行う方法はありますか?

24
bit-question

システムに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
33
Kevin

ケビンのソリューションは素晴らしい働きをします!頭の上から覚える方が簡単だと思うので、私が頻繁に使用した他のものは次のようなものです。

cp `ls | shuf -n 200` destination
2
Callum C
files=(*)
for (( i=0; i<200; i++ )); do
    keys=("${!files[@]}")
    rnd=$(( RANDOM % ${#keys[@]} ))
    key=${keys[$rnd]}
    mv "${files[$key]}" "$otherdir"
    unset files[$key]
done
2
glenn jackman

すべてのファイル名を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
2
user unknown

これを統計的にランダムにする必要がある場合は、RANDOM % ${#keys[@]}を使用しないでください。考慮してください:

  1. $RANDOMには32768個の一意の値があります
  2. 最初の選択は300要素のうち1要素です
  3. 32768 = 109 * 300 + 68

したがって、最初の項目を選択すると、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)
2
l0b0

Bashの1つのライナー:

ls original_directory/|sort -R|head -number_of_files_to_move|while read file; do cp "new_directory/"$file test; done
0
Peaceful