Страница man для GNU find содержит следующее:
-exec command ; [...] The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell.
Это от человека до find
(GNU findutils) 4.4.2.
Теперь я проверил это с помощью bash и dash, и оба не должны {}
маскироваться. Вот простой тест:
find /etc -name "hosts" -exec md5sum {} \;
Есть ли оболочка, для которой мне действительно нужно маскировать брекеты? Обратите внимание, что это не зависит от того, содержит ли найденный файл пробел (вызывается из bash):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Это изменяется, если найденный файл передается в подоболочку:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \;
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory
которая может быть решена путем:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
в отличие от:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
но это не то, о чем идет речь на странице руководства, не так ли? Так какая оболочка относится {}
по-другому?
Ответы:
Резюме : если когда-либо существовала расширенная оболочка
{}
, то это действительно устаревшая версия.В оболочке Bourne и в POSIX-совместимых оболочках фигурные скобки (
{
и}
) являются обычными символами (в отличие от(
и)
которые являются разделителями слов, такими как;
и&
, и[
и]
которые являются символами слияния). Следующие строки должны быть напечатаны буквально:Слово, состоящее из одной фигурной скобки, является зарезервированным словом , которое является специальным, только если оно является первым словом команды.
Ksh реализует расширение скобок как несовместимое расширение оболочки Bourne. Это можно отключить с помощью
set +B
. Bash подражает ksh в этом отношении. Zsh также реализует расширение скобок; там его можно отключить с помощьюset +I
илиsetopt ignore_braces
илиemulate sh
. Ни одна из этих оболочек{}
ни в коем случае не расширяется , даже если это подстрока слова (напримерfoo{}bar
), из-за обычного использования в аргументахfind
иxargs
.Single Unix v2 отмечает, что
Эта заметка была исключена в последующих версиях стандарта; что примеры
find
имеют некотируемые использования{}
, как это делают примеры дляxargs
. Возможно, там были исторические оболочки Борна, где их{}
нужно было процитировать, но они уже были бы действительно устаревшими системами.Реализации CSH у меня есть под рукой (OpenBSD 4.7, BSD CSH на Debian , Tcsh) все расширения
{foo}
до ,foo
но оставить в{}
покое.источник
bash
(см.$BASH_VERSION
). Расширение скобок очень живое и здоровое.{}
Синтаксис возник вcsh
, но{}
расширен в пустую строку. Новые оболочки признают, что это бессмысленно, но есть еще старыеcsh
.{}foo
расширится доfoo
, но{}
расширится до{}
(за исключением случаев, когда внутри запятых, но цитирование не поможет) и было задокументировано как таковое. Я проверил это для csh из 2BSD (первый выпуск), 2.79BSD, 2.8BSD и 2.11BSD.{}
Нужно быть указаны в версияхfish
оболочки До 3.0.0.А в оболочке rc (тоже
akanga
на основеrc
, но неes
):Вероятно, это не те оболочки, о которых авторы этой GNU считают документацией, когда они писали этот текст с тех пор, как он
fish
был впервые выпущен в 2005 году (хотя этот текст или что-то подобное уже существовало в 1994 году) иrc
изначально не был оболочкой Unix.Есть некоторые слухи о некоторых версиях
csh
(оболочка, которая ввела расширение скобки), требующих этого. Но трудно отдать должное этим, так как первый релизcsh
в 2BSD этого не сделал. Вот как тестируется в эмуляторе PDP11:И справочная страница из 2BSD
csh
четко гласит :Поэтому мне было бы очень странно, если бы последующая версия csh или tcsh позже это сломала.
В некоторых версиях можно было бы обойти некоторые ошибки. Все еще с этим 2BSD csh (то же самое в 2.79BSD, 2.8BSD, 2.11BSD):
Цитирование не помогает, хотя:
Вы можете процитировать всю команду подстановки:
Но это передает один аргумент этому внешнему эхо.
В
csh
илиtcsh
, вы должны указать,{}
когда не по отдельности, как в:(хотя этот вид
find
использования не переносим, так как некоторыеfind
расширяются только{}
сами по себе).источник
Одним словом
csh
.bash
и другие современные оболочки понимают, что пользователь, вероятно, не просит расширения с нулевой скобкой. (Современныйcsh
на самом делеtcsh
и может также обрабатывать{}
разумно сейчас.)источник
csh
. Не все используют утилиты GNU в Linux; на самом деле их довольно часто устанавливают на старых коммерческих системах Unix, в которых ограничено количество связанных команд. (Заменаcsh
в этих системах менее вероятна, потому что системные скрипты могут полагаться на индивидуальные особенности оригиналаcsh
, и даже если все пользователи были настроены на использование более новой версииcsh
,root
почти наверняка потребуется остаться в комплекте версии.)pdksh
, правильно ли поступает ... хотя правильный ответ на этот вопрос , вероятно, "настоящийksh
- это FOSS в наши дни"...
для ksh93, bash и zsh). Только (т) CSH расширяется{foo}
доfoo
, и даже она оставляет в{}
покое (по крайней мере , на недавнем BSD - х).