300개의 데이터 파일이 포함된 디렉터리가 있다고 가정합니다. 이 파일 중 200개를 무작위로 선택하여 다른 디렉토리로 이동하고 싶습니다. Unix/Linux에서 이를 수행할 수 있는 방법이 있습니까?
답변1
시스템에 이 기능이 있으면 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
답변2
통계적 무작위성이 필요한 경우에는 사용하면 안 됩니다 RANDOM % ${#keys[@]}
.
$RANDOM
32768개의 고유 값이 있습니다.- 첫 번째 선택은 300개 요소 중 1개입니다.
- 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)
답변3
files=(*)
for (( i=0; i<200; i++ )); do
keys=("${!files[@]}")
rnd=$(( RANDOM % ${#keys[@]} ))
key=${keys[$rnd]}
mv "${files[$key]}" "$otherdir"
unset files[$key]
done
답변4
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