Как переместить определенное количество случайных файлов в ОС 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 дляorder расширение глобуса на основе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% округляется в меньшую сторону).

Другие вопросы по тегам