按百分比将多个文件移动到多个目录

按百分比将多个文件移动到多个目录

我有一个包含100,000文件的目录。这些是我需要移动到三个不同目录的音频文件traindevtest。分别按80%10%和的顺序10%

mv `ls | head -500` ./subfolder1/

如果我们知道默认数量但不知道文件总数的百分比,则这会移动文件。我想知道是否有一种更简洁的方法将 dir 分成三个。

答案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

使用如下 shell 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% 长度。

文件的移动是使用数组切片(在bash)中完成的。切片是从length 的${arr[@]:offset:length}从零开始的偏移量开始的切片。如果缺少参数(如最后一次调用),切片将运行到数组末尾。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

相关内容