여러 파일을 여러 디렉터리로 백분율로 이동

여러 파일을 여러 디렉터리로 백분율로 이동

파일이 포함된 디렉터리 가 있습니다 100,000. 이것들은 세 개의 다른 디렉토리로 이동하는 데 필요한 오디오 파일 입니다 train. , 의 순서를 각각 누릅니다 .devtest80%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부터 시작하는 오프셋에서 시작하는 슬라이스 입니다. 인수가 누락된 경우(마지막 호출에서와 같이) 슬라이싱은 배열 끝까지 실행됩니다.offsetlengthlengthmv

아직 파일을 두 부분(정수 산술)으로 분할할 준비가 되지 않았으므로 각 디렉터리에 있는 최종 파일 수는 분명히 어느 정도 근사치일 것입니다. 파일 개수를 나눌 수 없는 경우 디렉터리에 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

관련 정보