Заметки о Unix: ограничения опции -exec команды find и стремление к удобству при реализации команд

в 12:59, , рубрики: UNIX, Блог компании RUVDS.com, Настройка Linux, системное администрирование

В материале о том, что в наши дни find, как правило, не нуждается в xargs, я отметил, что в конструкции '-exec ... {} +' скобки ('{}') (для имён файлов, генерируемых find) должны находиться в конце команды. В комментарии к той публикации анонимный читатель сказал, что это неприменимо к -exec-версии, которая запускает отдельную команду для каждого имени файла. В результате можно поместить заменяемое имя файла в любом месте команды. Это, как оказалось, относится не только к GNU Find, являясь стандартной возможностью, и я полагаю, что этого даже требует Single Unix Specification (SUS) для find.

Заметки о Unix: ограничения опции -exec команды find и стремление к удобству при реализации команд - 1

(SUS, в отношении аргументов -exec, вводит ограничения лишь на форму '+', предписывая размещать '{}' непосредственно перед '+'. Спецификация же для формы ';' просто говорит об использовании обычного списка аргументов, после чего в описании сказано, что '{}' в списке аргументов заменяется на текущий путь. Понять это всё довольно сложно, хотя подобное в SUS и POSIX — обычное дело.)

Разница между двумя формами -exec — это интересный вопрос, и эта разница, вероятно, существует из-за удобства реализации формы '+'. Поэтому предлагаю начать с самого начала. Когда применяют любую из форм -exec, команда find выполняет соответствующие команды, задействуя семейство системных вызовов exec() (и библиотечные функции), которым нужно, чтобы им передавался бы © массив с командами и с аргументами (то есть — это argv для новой команды). Реализация этого в конструкции, где выполняется одна замена ('-exec ... ;') проста: создают и заполняют массив argv, содержащий все аргументы -exec (и команды), и запоминают индекс параметра '{}' (если такой параметр есть; он не является обязательным). Каждый раз, когда выполняют команду, текущий путь помещают в ячейку argv и дело сделано.

При использовании ограниченной формы множественной замены это, в некотором роде, тоже можно сделать. Создаётся массив argv некоего размера, начало которого заполняют всеми фиксированными опциями, а потом присоединяют каждый путь к его концу в виде дополнительной опции, следя за общим размером всех аргументов до тех пор, пока не понадобится выполнить команду, что позволяет ограничивать размер массива. Когда всё готово, индекс, по которому должен быть размещён следующий путь, сбрасывается к стартовой позиции, к месту, где заканчиваются фиксированные опции, после чего всё повторяется.

Правда, если конструкция '{}' может размещаться где угодно — понадобится более сложная реализация, в которой надо будет делить фиксированные аргументы на две части, одна из которых идёт до '{}', а вторая — после. Начало argv тогда заполняется «предшествующими» фиксированными аргументами, потом в массив попадают пути, в виде дополнительных аргументов, до достижения лимита, а затем, до exec(), присоединяются «следующие» фиксированные аргументы, если такие имеются. Для реализации этого всего нужно не так уж и много дополнительного труда, но над этим, всё равно, надо поработать. Поэтому я вынужден выдвинуть теорию о том, что объём этого дополнительного труда оказался именно таким, чтобы программисты, реализующие команду в System V R4 (там эта возможность появилась впервые) выбрали бы ограниченную форму ради удобства разработки и ради того, чтобы в их коде было бы меньше ошибок (ведь код, который не надо писать, определённо, совсем не содержит ошибок).

(Уверен, что это — не единственная область Unix-команд, в которой можно заметить признаки стремления разработчиков к реализации того, что реализовывать удобнее. Но в случае с двумя версиями -exec команды find перед нами — яркий пример такого подхода.)

Сталкивались ли вы с какими-то особенностями Unix-команд, которые можно объяснить стремлением их создателей к удобству их реализации?

Автор: ru_vds

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js