Как переместить определенное количество случайных файлов в ОС Unix/Linux
Я сталкиваюсь с этой простой задачей, но мне также интересно, какой самый простой и короткий способ это сделать.
Мое предложение - переместить определенное количество случайных файлов из одного каталога в другой. Эта задача является частью создания двух наборов данных, которые мне нужны для машинного обучения: обучающий набор и набор для тестирования. Моя цель - убрать 10% файла из каталога, чтобы получить агата datasat, который я мог бы проверить на своем классификаторе, и получить обучающий набор из исходного каталога.
Итак, что является наиболее компактным типом для этой задачи "переместить n случайных файлов"?
Заранее спасибо - как обычно -
8 ответов
Используйте комбинацию 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
, но, вероятно, быстрее).
Альтернативная версия с
find
чтобы не было проблем с папками. Он копирует 31415 случайно выбранных файлов в
/home/user/dir/
find . -maxdepth 1 -type f | sort -R | head -31415 | xargs cp -t /home/user/dir/
Вы можете использовать генератор случайных чисел bash, который генерирует int между 0 и 32767, чтобы выбрать, следует ли помещать файл в set1 или set2. Что бы сделать:
for file in ./*; do
val=$RANDOM
if test $val -gt 3276; then
mv "$file" ../set1
else
mv "$file" ../set2
fi
done
Вопрос довольно старый, но для записи это работает на OSX.
Вы должны установить gshuf
с brew install coreutils
, затем используйте:
tenpercent=$((`ls | wc -l` * 10/100))
ls | gshuf -n $tenpercent | xargs -I {} mv {} destination/path/
Вы можете перемешать список файлов, используя shuf или sort -R. Но вам все равно нужно взять подмножество, которое вы можете сделать с головой / хвостом.
Вы также можете сделать это с помощью Python. Мне так легче.
Вот сценарий python, который я использую для перемещения случайного процента изображений, который также получает связанные наборы данных меток, обычно требуемые для наборов данных изображений CV. Обратите внимание, что это перемещает файлы, потому что я не хочу, чтобы мой тестовый обучающий набор данных был в моем наборе обучающих данных.
Я использую приведенные ниже обучающие наборы 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
Как правило, мы делаем это с помощью скрипта Python или Java-программы. Любой из них может использовать правильный ГСЧ для принятия случайных решений, а затем вызывать необходимые вызовы для перемещения файлов.
С оболочкой zsh:
mv -- *(oe['REPLY=$RANDOM'][1,10]) /path/to/destination/
Где мы используемoe
квалификатор glob дляo
rder расширение глобуса на основеe
оценку данного кода (который здесь возвращает случайное значение) и выберите первые 10.
В последних системах GNU и с оболочкой с поддержкой замены процессов в стиле ksh (ksh93, zsh, bash) вы можете сделать:
xargs -r0a <(ls -U --zero | shuf -zn10) mv -t /path/to/destination --
ls -U --zero
можно заменить наprintf '%s\0' *
это ГНУls
слишком стар, чтобы поддерживать--zero
. С той разницей, что если в текущем каталоге нет неспрятанного файла, вы получите ошибку о невозможности переместить файл с именем*
.
xargs -r0a <(shuf -zen10 -- *) mv -t /path/to/destination --
Также можно использовать как более правильный/надежный/эффективный вариант ответа @boechat107 , хотя с добавленной оговоркой, что вы можете столкнуться со слишком длинной ошибкой списка аргументов при попытке выполнитьshuf
если в текущем рабочем каталоге имеется большое количество нескрытых файлов. Приведенный выше подход должен подойти в этом отношении, посколькуprintf
обычно встроен в оболочки и поэтому не зависит от этого ограниченияexecve()
системный вызов.
Чтобы переместиться на 10% вместо 10, с помощью zsh:
files=(*(Noe['REPLY=$RANDOM']))
mv -- $files[1,$#files/10] /path/to/destination/
(10% округляется в меньшую сторону).