我面临着一个简单的任务,但是我也在想最简单和最短的方法是什么。
我的建议是将指定数量的随机文件从一个目录移动到另一个目录。这个任务是我为机器学习需要创建两个数据集的一部分:一个训练集和一个测试集。我的目标是从一个目录中移除10%的文件,以获得可用于测试分类器的数据集,并从源目录获取训练集。
那么,这个“移动n个随机文件”的任务最紧凑的打法是什么?
提前感谢您的帮助 - 像往常一样 -
我面临着一个简单的任务,但是我也在想最简单和最短的方法是什么。
我的建议是将指定数量的随机文件从一个目录移动到另一个目录。这个任务是我为机器学习需要创建两个数据集的一部分:一个训练集和一个测试集。我的目标是从一个目录中移除10%的文件,以获得可用于测试分类器的数据集,并从源目录获取训练集。
那么,这个“移动n个随机文件”的任务最紧凑的打法是什么?
提前感谢您的帮助 - 像往常一样 -
使用 shuf
和 xargs
的组合(最好查看它们的文档,使用 man
命令):
shuf -n 10 -e * | xargs -i mv {} path-to-new-folder
以上命令选择当前文件夹(*
部分)中的10个随机文件,然后将它们移动到新文件夹。
虽然较长,但此版本可能更易于理解:
ls | shuf -n 10 | xargs -i mv {} path-to-new-folder
shuf
只是生成标准输入的随机排列,并将结果限制为10个(就像使用head
一样,但可能更快)。
shuf
的版本为8.25
。 - boechat107ls
之后应用head -n <N>
或tail -n <N>
,例如。这将为shuf
产生一个较短的参数列表。如果需要,您可以重复此过程。 - boechat107ls | gshuf -n 10 | xargs -I {} mv {} path-to-new-folder
。 - Ibukun Muyidefor file in ./*; do
val=$RANDOM
if test $val -gt 3276; then
mv "$file" ../set1
else
mv "$file" ../set2
fi
done
你可以使用shuf或sort -R来随机打乱文件列表。 但你仍然需要取一个子集,可以使用head/tail命令来实现。
ls $source_dir | sort -R | head -${tobemoved} | xargs -i mv $target_dir/{}
- 或者类似的指令。 - Mats Peterssonsort -R
。 - Martin Baulig使用find
命令的替代版本以避免与文件夹相关的问题。它将31415个随机选择的文件复制到/home/user/dir/
中。
find . -maxdepth 1 -type f | sort -R | head -31415 | xargs cp -t /home/user/dir/
你也可以使用Python来完成这个任务。我认为这更容易。
以下是我使用的Python脚本,用于移动随机百分比的图像,并获取通常在计算机视觉图像数据集中所需的关联标签数据集。请注意,此脚本会移动文件,因为我不希望我的测试训练数据集在我的训练数据集中。
对于Yolo训练集,我将标签和图像放在同一个目录中,并且标签是txt文件,因此我使用以下代码:
import numpy as np
import os
import random
#set directories
directory = str('/MauiData/maui_complete_sf_train')
target_directory = str('/MauiData/maui_complete_sf_test')
data_set_percent_size = float(0.07)
#print(os.listdir(directory))
# list all files in dir that are an image
files = [f for f in os.listdir(directory) if f.endswith('.jpg')]
#print(files)
# select a percent of the files randomly
random_files = random.sample(files, int(len(files)*data_set_percent_size))
#random_files = np.random.choice(files, int(len(files)*data_set_percent_size))
#print(random_files)
# move the randomly selected images by renaming directory
for random_file_name in random_files:
#print(directory+'/'+random_file_name)
#print(target_directory+'/'+random_file_name)
os.rename(directory+'/'+random_file_name, target_directory+'/'+random_file_name)
continue
# move the relevant labels for the randomly selected images
for image_labels in random_files:
# strip extension and add .txt to find corellating label file then rename directory.
os.rename(directory+'/'+(os.path.splitext(image_labels)[0]+'.txt'), target_directory+'/'+(os.path.splitext(image_labels)[0]+'.txt'))
continue
brew install coreutils
安装gshuf
,然后使用以下命令:tenpercent=$((`ls | wc -l` * 10/100))
ls | gshuf -n $tenpercent | xargs -I {} mv {} destination/path/
使用zsh shell:
mv -- *(oe['REPLY=$RANDOM'][1,10]) /path/to/destination/
我们在编写代码时使用oe
全局限定符来根据给定代码的e
valuation(这里返回一个随机值)对全局扩展进行排序,并选择前10个。
在最近的GNU系统中,以及支持ksh-style进程替换的shell(ksh93、zsh、bash),您可以执行以下操作:
xargs -r0a <(ls -U --zero | shuf -zn10) mv -t /path/to/destination --
ls -U --zero
可以被替换为 printf '%s\0' *
,因为 GNU 的 ls
版本太旧不支持 --zero
。不同的是,如果当前目录中没有非隐藏文件,则会出现有关无法移动名为 *
的文件的错误。
xargs -r0a <(shuf -zen10 -- *) mv -t /path/to/destination --
可以作为 @boechat107's answer 更正确/可靠/高效的变体,但需要注意的是,如果当前工作目录中有大量非隐藏文件,则在尝试执行 shuf
时可能会遇到 参数列表过长 错误。上面基于printf
的方法在这方面应该是可以正常运行的,因为printf
通常内置于shell中,所以不受execve()
系统调用的限制。
要移动10%而不是10,在zsh中:
files=(*(Noe['REPLY=$RANDOM']))
mv -- $files[1,$#files/10] /path/to/destination/
(向下取整)的10%。
ls -1 | wc -l
number=$RANDOM
let "number %= $file_list_no"echo "选择要移动的随机文件数:$number of $file_list_no"` - java_xof