Ограничить количество совпадений команды поиска

Вы можете добавить параметр загрузки к параметру по умолчанию, используемому вашим загрузчиком, добавив его к значению GRUB_CMDLINE_LINUX_DEFAULTв /etc/default/grub. После этого запустите sudo update-grub, чтобы обновить конфигурацию.

9
19.12.2019, 13:17
5 ответов

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


Использование оболочки zsh

mv./**/*(-.D[1,1000]) /path/to/collection1    # move first 1000 files
mv./**/*(-.D[1,1000]) /path/to/collection2    # move next 1000 files

Подстановочный шаблон ./**/*(-.D[1,1000])будет соответствовать всем обычным файлам (или символическим ссылкам на такие файлы )в текущем каталоге или под ним, а затем вернет 1000 первых из них. -.ограничивает поиск обычными файлами или символическими ссылками на них,в то время как Dдействует как dotglobвbash(соответствует скрытым именам ).

Предполагается, что сгенерированная команда не станет слишком большой из-за расширения шаблона подстановки при вызове mv.

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

pathnames=(./**/*(-.D) )

mv $pathnames[1,1000]    /path/to/collection1
mv $pathnames[1001,2000] /path/to/collection2

Для рандомизации массива pathnamesпри его создании (вы упомянули о желании переместить случайные файлы):

pathnames=(./**/*(-.Doe['REPLY=$RANDOM']) )

Вы могли бы сделать то же самое в bash(, за исключением того, что вы не можете легко перетасовать результат совпадения glob в bash, за исключением возможной передачи результатов через shuf, поэтому я пропущу этот бит):

shopt -s globstar dotglob nullglob

pathnames=()
for pathname in./**/*; do
    [[ -f $pathname ]] && pathnames+=( "$pathname" )
done

mv "${pathnames[@]:0:1000}"    /path/to/collection1
mv "${pathnames[@]:1000:1000}" /path/to/collection2
mv "${pathnames[@]:2000:1000}" /path/to/collection3
17
27.01.2020, 20:04

Я думаю, это невозможно напрямую с помощью find, но вы можете использовать канал с головой и xargs, например:

find... | head -1000 | xargs -i mv "{} /path/to/collection1"

Это перемещает первые 1000 файлов в коллекцию1.

4
27.01.2020, 20:04

Я не думаю, что это можно сделать, используя только find. Вы можете использовать что-то вроде:

find [... your parameters...] -print0 | head -z -1000 | xargs -0 mv -t /path/to/collection

-print0, -zи -0работают вместе, чтобы убедиться, что все работает даже с переводом строки в именах файлов.

10
27.01.2020, 20:04

Вы можете реализовать новые тесты для find, используя-exec:

seq 1 1000 |
find. -exec read \; -exec mv {} /path/to/collection1 +

переместит первые 1000 найденных файлов в /path/to/collection1.

Это работает следующим образом:

  • seq 1 1000выводит 1000 строк, переданных в find;
  • -exec readсчитывает строку, терпит неудачу, если канал закрыт (, когда выход seqисчерпан );
  • Если предыдущее -execзавершается успешно, -exec mv...выполняет перемещение.

-exec... +работает так, как вы ожидаете.:readбудет запускаться один раз за итерацию, но findбудет накапливать совпадающие файлы и вызывать mvкак можно меньше раз.

Это основано на том факте, чтоfind's -execзавершается успешно или неудачно в зависимости от состояния выхода выполняемой команды :, когда readзавершается успешно, findпродолжает обработку действий, указанных выше (, поскольку оператор по умолчанию — «и» ), и когда он терпит неудачу, findостанавливается.

Если ваш findподдерживает действие -quit, вы можете использовать его для повышения эффективности:

seq 1 1000 |
find. \( -exec read \; -o -quit \) -exec mv {} /path/to/collection1 +

Без этого findбудет проверять каждый отдельный файл, даже если он сохранит только 1000 для mv.

Я предполагаю, что readдоступен как внешняя команда и реализует спецификацию POSIX дляread; если это не так, вместо этого можно использовать sh -c read. В обоих случаях findзапускает отдельный процесс для каждого проверяемого файла.

18
27.01.2020, 20:04

Ответ Стивенса 264963, вероятно, лучше всего подходит для моего случая использования -, но есть простой обходной путь для случая использования -в этом вопросе с помощью только find и head:

find. [checks] -print -exec... | head

-printбудет оцениваться перед-exec(По крайней мере, в CentOS 8 ), и канал к голове приведет к выходу find, когда headзакроет канал.

1
18.03.2021, 19:27

Теги

Похожие вопросы