Использование заключающих в скобки {} в качестве аргументов команд и их параметров

11

Примеры

Недавно я нашел примеры использования пар заключающих в скобки паролей {}, между которыми нет открывающей и закрывающей скобок, в качестве аргументов команд и даже их параметров:

cat foo | xargs -I{} echo {}

find . -size 0 -exec rm -i {} \;

Нет документации

Моя проблема в том, что я не могу найти документацию в Руководстве по GNU Bash, которая описывает использование {}в таком контексте, как в примерах выше.

Я не думаю, что это расширение параметра , потому что знак доллара должен предшествовать фигурным скобкам в расширении параметра, как в ${}.

Это также не может быть расширением скобки , потому что оно принимает форму {x..y[..incr]}, где xи yне является обязательным.

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

Вопросов

  1. Что вообще означает пара заключающих в скобки пар {}в качестве аргумента для любой команды, которая ее принимает?

  2. Где я могу найти документацию, которая описывает использование в {}качестве аргументов?

Нико Гамбт
источник
Некоторые команды имеют эту опцию {}- то есть targetsдействовать, с помощью findкоманды это удалить / rmнайти файлы.
Туйен Фам

Ответы:

16

Эти фигурные скобки оставлены в покое bash; они принадлежат findи xargs, соответственно, и описаны на их страницах руководства.

man find

-exec команда ;

Выполнить команду ; true, если возвращается 0 статус. Все последующие аргументы для поиска принимаются в качестве аргументов команды, пока не ;встретится аргумент, состоящий из . Строка {}заменяется на текущее имя файла, обрабатываемое везде, где оно встречается в аргументах команды, а не только в аргументах, где оно одиночно, как в некоторых версиях find. Обе эти конструкции, возможно, должны быть экранированы (с помощью \) или заключены в кавычки, чтобы защитить их от расширения оболочкой. В разделе ПРИМЕРЫ приведены примеры использования -execопции. Указанная командазапускается один раз для каждого соответствующего файла. Команда выполняется в начальном каталоге. Существуют неизбежные проблемы безопасности, связанные с использованием -exec действия; Вы должны использовать -execdirопцию вместо этого.

-exec команда {} +

Этот вариант -execдействия запускает указанный команду для выбранных файлов, но командная строка создается путем добавления каждого выбранного имени файла в конце; общее количество вызовов команды будет намного меньше, чем количество совпавших файлов. Командная строка строится во многом так же, как и xargsее командные строки. В {}команде допускается только один экземпляр . Команда выполняется в начальном каталоге. Если findвозникает ошибка, это может иногда вызывать немедленный выход, поэтому некоторые ожидающие команды могут вообще не выполняться. Этот вариант -execвсегда возвращает истину.

-execdir команда ;

-execdir команда {} +

Как ; в противном случае злоумышленник может выполнить любые команды, которые ему нравятся, оставив файл с соответствующим именем в каталоге, в котором вы будете работать . То же самое относится к наличию записей, в которых они пусты или не являются абсолютными именами каталогов. Если возникает ошибка, это может иногда вызывать немедленный выход, поэтому некоторые ожидающие команды могут вообще не выполняться. Результат действия зависит от того, используется или вариант; Команда всегда возвращает истину, а команда возвращает истину, только если команда возвращает 0.-exec , но указанная команда запускается из подкаталога, содержащего соответствующий файл, который обычно не является каталогом, в котором вы начали поиск. Это гораздо более безопасный метод для вызова команд, поскольку он позволяет избежать условий гонки во время разрешения путей к соответствующим файлам. Как и в случае с -exec действием, + форма -execdir создаст командную строку для обработки более одного сопоставленного файла, но при любом вызове команды будут перечислены только файлы, которые существуют в одном и том же подкаталоге. Если вы используете эту опцию, вы должны убедиться, что ваша $PATHпеременная среды не ссылается.-execdir$PATHfind+;-execdir {} +-execdir {} ;

man xargs

-I заменить-Обл

Заменить вхождения replace-str в исходных аргументах именами, считанными из стандартного ввода. Кроме того, пробелы без кавычек не заканчивают элементы ввода; вместо этого разделителем является символ перевода строки. Подразумевается -xи -L 1.

-i[ replace-str ], --replace[ =replace-str ]

Эта опция является синонимом для -Ireplace-str, если указан replace-str . Если аргумент replace-str отсутствует, эффект такой же, как и -I{}. Эта опция устарела; используйте -Iвместо этого.

Редактировать: и здесь ПОЧЕМУ bash игнорирует эти фигурные скобки:

man bash

{ список; }

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

Для акцента: список должен заканчиваться символом новой строки или точкой с запятой .

Дзынь
источник
1
Спасибо! Меня раздражает, что тот, кто написал, man xargsдаже не удосужился объяснить, что на {}самом деле означает, и при этом автор не перенаправил (без каламбура) читателя к объяснению -execна странице руководства find.
Нико Гамбт
@NikoGambt - Сочувствую ...
Дзынь
5
@NikoGambt Ну, {} на самом деле ничего не значит для xargs, за исключением того, что это значение по умолчанию для -i, которое не рекомендуется. Я не уверен, какое объяснение необходимо после этого. В приведенном вами примере это также могло бы быть xargs -Iab echo ab; это чисто произвольный выбор.
Random832
@ Random832 Пройдя еще какое-то тестирование -I, я теперь понимаю, что на самом деле делает эта опция. Да, {}произвольно, как вы сказали. Я был просто смущен объяснением If the replace-str argument is missing, the effect is the same as -I{}. Если бы -Iбез аргумента было так же, как -I{}, то cat foo | xargs -I echo {}вы получите тот же результат, что и при запуске cat foo | xargs -I{} echo {}. Однако они не одинаковы. Первый - ошибка, и что еще больше смутило меня - это сообщение об ошибке xargs: {}: No such file or directory, но это только из-за реализации.
Нико Гамбт
1
@NikoGambt -I(верхний регистр I) не может быть запущен без аргумента. Аргумент -Iбыл echo. Это основное различие между -Iи -i(и причина -i устарела, так как опции с необязательными аргументами редки и сбивают с толку)
Random832