파일이 포함된 디렉터리 가 있습니다 100,000
. 이것들은 세 개의 다른 디렉토리로 이동하는 데 필요한 오디오 파일 입니다 train
. , 의 순서를 각각 누릅니다 .dev
test
80%
10%
10%
mv `ls | head -500` ./subfolder1/
기본 수는 알고 있지만 총 파일 수의 백분율은 모르는 경우 파일을 이동합니다. 디렉토리를 3개로 나누는 더 깔끔한 방법이 있는지 궁금합니다.
답변1
ls
출력을 입력으로 사용하는 것은 일반적으로 좋은 생각이 아닙니다.
작은 스크립트로 원하는 것을 얻을 수 있습니다.
#! /bin/sh
# file counter
cnt=0
# for each file (replace *.* by *.mp3 to restrict to some files)
for i in *.*
do
# create a number for 0 to 9 from the counter
a=$(( cnt%10 ))
# for 8 files on 10,
if [ $a -lt 8 ]
then
# move file to train folder (think to remove `echo`)
echo mv "$i" train/
# for one file on 10 (a is 8)
elif [ $a -lt 9 ]
then
# move file to dev folder (think to remove `echo`)
echo mv "$i" dev/
# for one file on 10 (a is 9)
else
# move file to test folder (think to remove `echo`)
echo mv "$i" test/
fi
# and update the counter
cnt=$((cnt+1))
done
답변2
다음 쉘을 사용하십시오 bash
.
#!/bin/bash
# Get all names.
# This assumes that *.mp3 matches only the things that we'd like to move.
names=( *.mp3 )
# Create our destination directories.
mkdir train dev test
# Calculate some numbers...
n=${#names[@]} # 100% of the files
# Six files at least are needed...
# (or one of the directories will be empty)
if [ "$n" -lt 6 ]; then
printf 'Only %d files\n' "$n"
exit 1
fi
n80=$(( (80*n)/100 )) # 80% of the files
n10=$(( (n - n80)/2 )) # 10% of the files
# Move the files...
mv "${names[@]:0:n80}" train # Move the 80%
mv "${names[@]:n80:n10}" dev # Move the 10%
mv "${names[@]:n80+n10}" test # Move the rest
이는 이름이 지정된 배열로 이동하려는 파일의 이름을 읽습니다 names
. *.mp3
사용된 패턴이 일치한다고 가정오직그리고모두관심 있는 이름입니다(필요에 맞게 이 패턴을 수정하세요).
그런 다음 배열의 80%와 10% 길이를 계산합니다.
파일 이동은 배열 슬라이싱(in)을 사용하여 bash
수행 됩니다. 슬라이스는 length 에서 ${arr[@]:offset:length}
0부터 시작하는 오프셋에서 시작하는 슬라이스 입니다. 인수가 누락된 경우(마지막 호출에서와 같이) 슬라이싱은 배열 끝까지 실행됩니다.offset
length
length
mv
아직 파일을 두 부분(정수 산술)으로 분할할 준비가 되지 않았으므로 각 디렉터리에 있는 최종 파일 수는 분명히 어느 정도 근사치일 것입니다. 파일 개수를 나눌 수 없는 경우 디렉터리에 test
파일이 하나 더 추가될 수 있습니다.dev
이는 또한 한 번의 작업으로 파일의 80%를 이동할 수 있을 만큼 충분히 짧은 파일 이름에 의존합니다. 그렇지 않은 경우 mv
마지막 세 줄(줄)을 다음으로 변경 해야 합니다.
for name in "${names[@]:0:n80}"; do
mv "$name" train
done
for name in "${names[@]:n80:n10}"; do
mv "$name" dev
done
for name in "${names[@]:n80+n10}"; do
mv "$name" test
done