сколько вызовов команд с командой find -exec {} +

Вы можете создать псевдоним в своем ~/.bashrc:

alias ls="ls --color=always"

Вы также можете установить переменную окружения LS _COLORS, проверьте примеры в Интернете, просто найдите ее с помощью выбранной вами системы $search _, убедитесь, что вы exportее добавили в ~/.bashrc

export LS_COLORS="..."

В общем, прочтите о ~/.bashrcи о том, что вы можете с ним сделать, помните, что alias— ваш друг в командной строке.

2
16.09.2020, 01:11
3 ответа

Используемый буфер зависит от версии findи, по-видимому, имеет размер около 256 КБ в коробке SuSE, которую я могу найти здесь.

Таким образом, чтобы рассчитать, сколько раз вызывается "команда", вам нужно знать длину каждого найденного пути к файлу, тогда она будет (примерно )суммой всех длин путей, увеличенных на единицу для разделительный пробел минус сама команда, разделенная на размер буфера.

. вы найдете 20 000 файлов со средней длиной пути 200 байт, то есть 4 020 000 байт, разделить на 256 КБ равно 15,33, поэтому вам потребуется около 16 вызовов.

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

См. здесь для потока (с исходным кодом ), где размер, как сообщается, составляет 32 КБ и считается излишне малым (теперь, когда я думаю об этом, может быть, мой собственныйfindэто с использованием syslimits. я не экспериментировал ); Версия coreutilsпо заключению кажется в четыре раза больше, то есть 128 Кб .

3
18.03.2021, 23:04

Предварительное примечание :руководство и ваш вопрос используют commandдля обозначения команды, но поскольку POSIX определяет утилиту с буквальным именем command, мой ответ будет использовать cmmnd.


Если вы хотите на самом деле запуститьcmmnd(s )и просто подсчитать количество вызовов (, чтобы узнать его после завершенияfind), создайте оболочку, которая делает то, что вы можете посчитать. (например печатает в stderr, печатает в файл журнала, издает звуковой сигнал )и, в конце концов, запускает cmmnd. Пример:

#!/bin/sh
echo "invoking cmmnd" >&2
cmmnd "$@"

Затем используйте wrapperвместо cmmndвнутри find.

Примечание findбудет использовать /absolute/path/to/wrapperпри создании не слишком длинных команд; тогда оболочка будет использовать /absolute/path/to/cmmnd. Если последний длиннее, то какая-то командная строка (с ), содержащая его, может оказаться слишком длинной в любом случае. Так что этот подход не так прост, как хотелось бы. Вы можете расширить прежний путь, предоставив его дословно findс дополнительными косыми чертами (, например./absolute/path/to/////wrapper).


Теперь я предполагаю, что вы хотите узнать число до того, как вы решите запуститьcmmnd(с ). Например, в случае, когда вызов cmmndдважды является плохой вещью (по какой-либо причине ), и вы хотите убедиться, что findзапустит его ровно один раз.

Вышеупомянутая оболочка с закомментированным cmmnd "$@"может быть использована. Ниже приведены несколько других идей (, которые, в конце концов, не так уж отличаются друг от друга ).

Предположим, вы хотите сделать это:

find. -exec cmmnd … {} +

(где обозначает постоянные аргументы ). Узнайте, каков на самом деле абсолютный путь к cmmnd. Например. это может быть /bin/cmmnd. Затем запустите что-то вроде этого:

find. -exec /aaa/zzzzz … {} +

где /aaa/zzzzz— несуществующая команда, имя которой имеет ту же длину, что и /bin/cmmnd. Теперь findбудет строить командные строки с /aaa/zzzzz, которые будут иметь ту же длину, что и командные строки с /bin/cmmnd. Вы получите

find: '/aaa/zzzzz': No such file or directory

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

find. -exec /aaa/zzzzz … {} + 2>&1 | wc -l

не лучший, потому что findможет также печатать, например. permission deniedдля некоторых файлов, с которыми он сталкивается. Но если вы создадите /aaa/zzzzzкак допустимый исполняемый файл, который печатает ровно одну строку (, это может быть пустая строка ), тогда это должно работать:

find. -exec /aaa/zzzzz … {} + | wc -l

Еще одно улучшение заключается в том, чтобы назвать инструмент/a(вместо/aaa/zzzzz)и называть его /////aили /////////////////aи т. д., в зависимости от необходимой длины. Пример:

find. -exec /////////a … {} + | wc -l

Для полноты картины aможет выглядеть так:

#!/bin/sh
echo

Это почти как наша оболочка без cmmnd "$@", но использует стандартный вывод.

Примечания:

  • Точное количество /символов не имеет значения. Ошибка нескольких не изменит результат кардинально . Если вам нужен оценочный результат , вы можете вслепую использовать ///////////aили около того, если только путь к cmmndне является необычно длинным. Обратите внимание, что использование точно /aдаст вам нижнюю границу.

  • На практике перед -exec cmmnd … {} +часто проводятся другие тесты. Если вы замените cmmndна /////////aили около того, другие тесты все равно будут выполняться. Вы не должны их опускать, потому что они определяют, какие пути попадают в -execв первую очередь. Но если тесты что-то делают или изменяют, возможно, их выполнение без cmmndнеправильно.

    . вы можете удалить файлы с помощью -delete -exec cmmnd … {} +, где cmmndсоздает отчет об удаленных файлах. В этом случае использование /////////aприведет к удалению файлов без создания отчета . Так что подумайте, прежде чем действовать.

  • Убедитесь, что тесты/действия/что угодно, кроме -exec /////////a … {} +, ничего не выводят на стандартный вывод. Или пусть /aиспользует какой-то другой канал.

  • Обработка заданного дерева каталогов (с )и выполнение (других )тестов может занять некоторое время даже безcmmnd(с ).

2
18.03.2021, 23:04

Ну, стандартный текст говорит:

The size of any set of two or more pathnames shall be limited such that execution of the utility does not cause the system's {ARG_MAX} limit to be exceeded.

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

Сколько именно вызовов он делает, зависит от реализации и, вероятно, вас не должно слишком волновать. Стандарт обещает, что вызовы одного и того же предложения -execне перекрываются, что может иметь значение для корректности, если вы выполняете что-то, что имеет внешнее состояние.

Однако в Linux фактический максимальный размер аргументов командной строки зависит от размера стека и может быть косвенно изменен с помощью ulimit -s. И оказывается, что в отличие от, например. xargs, findв моем Debian и Ubuntu на самом деле не проверяет ограничение во время выполнения, поэтому теоретически возможно столкнуться с проблемами.

$ mkdir bar
$ touch bar/{00000..99999}
$ ulimit -Ss 512
$ getconf ARG_MAX
131072
$ find bar -type f -exec sh./args.sh {} +
find: ‘sh’: Argument list too long
find: ‘sh’: Argument list too long
...

Однако значение по умолчанию для ulimit -sравно 8192, так что у вас вряд ли возникнет эта проблема, за исключением очень ограниченной системы.

0
18.03.2021, 23:04

Теги

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