Почему 'find -exec cmd {} +' должен заканчиваться на '{} +'?

11

Предисловие: я понимаю разницу между -exec {} \;& -exec {} +. У меня также нет проблемы как таковой , мне просто интересно узнать о семантике find.


Когда заканчивается -execаргумент +вместо ;, нам нужно завершить это {} +, например:

# FreeBSD find
$ find . -type f -exec cp {} /tmp +
find: -exec: no terminating ";" or "+"

# GNU find is even more cryptic:
$ find: missing argument to `-exec'

Использование ;в этих примерах вместо +прекрасно работает (но, очевидно, делает что-то еще).

Из POSIX :

-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +

... Только знак «плюс», который следует сразу за аргументом, содержащим только два символа « {}», должен быть акцентирован на конце основного выражения. Другие варианты использования знака «плюс» не должны рассматриваться как особые.

Другими словами, при использовании +, команда должна заканчиваться на {} +.

Почему это? А почему только с то +а не то ;? Сначала я подумал, может быть, чтобы избежать конфликтов с именами файлов, которые содержат +, но имена с надписью ;вроде бы работают нормально? Мне трудно поверить, что это ограничение является произвольным ...

Мартин Турной
источник
3
Кстати, на странице POSIX также сказано, что The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210и в этом документе вы найдете больше деталей, например:Note that the "+" is only treated as special if it immediately follows "{}". This minimises the chances of causing problems with existing uses of "+" as an argument with "-exec".
don_crissti

Ответы:

5

Обоснование дано в спецификации POSIX является:

"-exec ... {} +"Синтаксис принят был результатом IEEE PASC интерпретации 1003,2 # 210. Следует отметить, что это несовместимое изменение в стандарте ISO / IEC 9899: 1999. Например, следующая команда печатает все файлы с '-'именем после их имени, если они являются обычными файлами, и '+'другим способом:

find / -type f -exec echo {} - ';' -o -exec echo {} + ';'

Изменение лишает законной силы использование как это. Несмотря на то, что в предыдущем стандарте говорилось, что это использование будет работать, на практике многие его не поддерживали, и разработчики стандарта решили, что теперь лучше заявить, что это недопустимо.

PASC Интерпретация 1003.2 # 210 более подробно рассказывает об истории -exec … {} +. Он существовал в нескольких системах Unix до того, как был принят POSIX; отчет о дефектах прослеживает его до SVR4 (где он был в значительной степени недокументирован). Сообщение о дефекте оправдывает несовместимое изменение как незначительное влияние на практике:

Обратите внимание, что «+» рассматривается как особый, только если сразу следует «{}». Это минимизирует вероятность возникновения проблем с существующим использованием «+» в качестве аргумента с «-exec».

Хотя добавление поддержки -exec … {} +нарушило бы некоторые соответствующие приложения, такие как приведенный выше пример, их меньше, чем если бы это -exec … {} … +было разрешено.

Другая причина, возможно, ограничивающая {}быть последним аргументом - простота реализации. Если {}было разрешено в любом месте списка аргументов -exec, findпрограмма должна была бы построить командную строку, скопировав статические аргументы, затем переменную часть, затем другую статическую часть. Это затруднило бы создание списка аргументов и учет ограничения по размеру. Сложность минимальна, но разработчики любят срезать углы. Поддержка нескольких заменяемых экземпляров {}(если -exec {} foo +это работает, логично ожидать, что это -exec {} foo {} +будет так же) будет значительно сложнее.

Жиль "ТАК - перестань быть злым"
источник