Ускорение случайной сортировки и удаления (rm) для нескольких каталогов

Ускорение случайной сортировки и удаления (rm) для нескольких каталогов

Запуск MacOS в терминале, который по сути является BSD, поэтому я размещаю свой вопрос здесь, а не на askdifferent. Я хочу обрезать свой набор данных изображений на последующих этапах, удаляя файлы случайным образом. В некоторых каталогах более 1 миллиона jpg. Мои данные находятся в главном каталоге с подкаталогами, максимальная глубина которых составляет всего 1:

-master
     -data1
       image.jpgs
     -data2
       image.jpgs
     -data3
       image.jpgs
     -data4
       image.jpgs
... and so forth

Я нашел эту ссылку:

https://superuser.com/questions/1186350/удалить-все-кроме-1000-случайных-файлов-в-каталоге

... и придумал:

for f in *.jpg; do find "$f" -type f -print0 | sort -R | tail -n +50001 | xargs -0 rm; done

Хотя это и работает, я бы хотел, чтобы это делалось рекурсивно для подкаталогов, чтобы мне не приходилось вручную делать это для каждого каталога. Поэтому мои вопросы/запросы:

  1. Можно ли как-то оптимизировать это, чтобы ускорить?
  2. Будет ли sort/tail возвращать ошибку, если обнаружит каталог, содержащий менее 50 000 файлов?

решение1

Проверив ссылку на исходный пост, похоже, что ваш цикл на самом деле должен быть таким:

for d in */; do find "$d" -iname '*.jpg' -type f -print0 | sort -zR | tail -zn +50001 | xargs -0r rm; done

Запускается из masterкаталога.

Параметры -zдля sortи tailнеобходимы, так как входные данные разделены нулем. Ни один из них не будет жаловаться, если строк меньше 50000 — sortему все равно, и tailон ничего не выведет, так как после 50000-й строки ничего нет. rmможет жаловаться на запуск без аргументов, но -rпараметр GNU xargsпредотвратит его запуск, rmесли он не получит входных данных (BSD xargs в этом не нуждается, но, вероятно, не будет жаловаться).

Наконец, но самое важное, -zопция для ввода с разделителями-нулями, вероятно, не будет поддерживаться BSD tail. Вам понадобится GNU tail, который можно установить с помощью homebrew.

Вероятно, вы могли бы обойтись без строк, разделенных нулем, если бы гарантированно не содержали в своих именах файлов пробелы, символы новой строки, кавычки, обратные косые черты и т. д. В этом случае:

for d in */; do find "$d" -type f | sort -R | tail -n +50001 | xargs rm; done

Связанный контент