Удалить все кроме 1000 случайных файлов в каталоге

13

Я позволил сценарию генерации данных работать слишком долго, теперь у меня есть более 200 000 файлов, которые мне нужно сократить до 1000. Из командной строки Linux есть простой способ удалить все, кроме 1000 этих файлов, где файлы, которые будут сохранены не будет зависеть от имени файла или любого другого атрибута?

Малкольм Реган
источник
Был ли процесс, который создал файлы, имел характеристику, которая связывала каждый файл с предыдущим? Если так, то при случайном выборе было бы важно получить репрезентативную выборку. Если процесс генерирует файлы, которые являются случайными по своей природе, вы можете просто удалить все после первой 1000.
fixer1234

Ответы:

15

Удалить все кроме 1000 случайных файлов в каталоге

Код:

find /path/to/dir -type f -print0 | sort -zR | tail -zn +1001 | xargs -0 rm

Объяснение:

  1. Список всех файлов в /path/to/dirс find;
    • print0: использовать \0( нулевой символ ) в качестве разделителя строк; поэтому пути к файлам, содержащие пробелы / переводы строк, не нарушают сценарий
  2. Перемешать список файлов с помощью sort;
    • -z: использовать \0(нулевой символ) в качестве разделителя вместо \n(перевод строки)
    • -R: случайный порядок
  3. Уберите первые 1000 строк из рандомизированного списка с помощью tail;
    • -z: обрабатывать список как разделенный нулями (так же, как и с sort)
    • -n +1001: показать строки, начинающиеся с 1001 (т.е. опустить первые 1000 строк)
  4. xargs -0 rm - удалить оставшиеся файлы;
    • -0: опять с нулевым разделением

Почему это лучше, чем решение Quixotic *:

  1. Работает с именами файлов, содержащими пробелы / переводы строк.
  2. Не пытается создать какие-либо каталоги (которые могут уже существовать, кстати.)
  3. Не перемещает файлы, даже не касается 1000 «счастливых файлов», кроме перечисления их с помощью find.
  4. Позволяет избежать пропуска файла в случае, если вывод по какой-либо причине findне заканчивается на \n(перевод строки).

* - кредит на Quixotic для | sort -R | head -1000, дал мне отправную точку.

RLD.
источник
При работе на CentOS 6 я получал ошибки о недопустимых операндах. К счастью, меня не интересуют пробелы в файловых путях, поэтому удаление этих операндов сработало для меняfind . -type f | sort -R | tail -n +1001 | xargs rm
Брэд,
@brad Не могли бы вы предоставить сообщения об ошибках и свою версию find? Я постараюсь улучшить свой ответ, просто нужно немного поработать с ним.
сл.
3
tail: invalid option -- 'z'версия хвоста у меня 8,4
Брэд
Я бы добавил --no-run-if-empty в xargs, чтобы избежать ошибки, если нет файла (после запуска его дважды для примера)
fraff
1

Используйте временный каталог, затем findвсе ваши файлы, перемешайте список со списком sortи переместите верхнюю 1000 списка во временный каталог. Удалите остальные, затем переместите файлы обратно из временного каталога.

$ mkdir ../tmp-dir
$ find . -type f | sort -R | head -1000 | xargs -I "I" mv I ../tmp-dir/
$ rm ./*
$ mv ../tmp-dir/* .

Если вы xargsжалуетесь на длину строки, используйте меньшее число с headи повторяйте команду по мере необходимости (т.е. измените -1000на -500и запустите ее дважды, или измените на -200и запустите ее 5 раз).

Он также не сможет обрабатывать имена файлов, которые содержат пробелы; а @ ответ RLD в шоу, вы можете использовать find«s -print0аргумент, -zаргументы sortи head, и -0с , xargsчтобы обеспечить надлежащую обработку имен файлов.

Наконец, если tmp-dirуже существует, вы должны заменить имя каталога, который не существует.

донкихотский
источник
Это не удастся, если любое из имен файлов, перечисленных с findпомощью пробела.
сл.
0

Для пользователей Mac должен сделать следующий скрипт.

find . -type f -print0 | tr '\0' '\n' | sort -R | tail -n +10000 | tr '\n' '\0' | xargs -0 rm

trпозволит sort и tail работать со списками \nвместо \0.

Лука Ди Лиелло
источник
-2

Самым простым может быть rm -rf каталога, а затем перезапустить сценарий генерации данных, убедившись, что он не выполняется слишком долго.

Ларс Поулсен
источник
Это не то, что спросил ОП. Может быть, это невозможно.