Используя следующую команду, не мог бы кто-нибудь объяснить, для чего конкретно нужны конечные фигурные скобки ({}) и знак плюс (+)?
И как команда будет действовать иначе, если они будут исключены из команды?
find . -type d -exec chmod 775 {} +
Фигурные скобки будут заменены результатами find
команды, и chmod
они будут запущены для каждого из них. В +
марке find
пытается работать как несколько команд , как это возможно (так, chmod 775 file1 file2 file3
в отличие от chmod 755 file1
, chmod 755 file2
, chmod 755 file3
). Без них команда просто выдает ошибку. Это все объясняется в man find
:
-exec command ;
Выполнить команду ; true, если возвращается 0 статус. Все последующие аргументы для
find
принимаются в качестве аргументов команды, пока не;
встретится аргумент, состоящий из ' '. Строка '{}
' заменяется текущим именем файла, обрабатываемым везде, где оно встречается в аргументах команды, а не только в аргументах, где оно одиночно, как в некоторых версияхfind
. ...
-exec command {} +
Этот вариант
-exec
действия запускает указанную команду для выбранных файлов, но командная строка создается путем добавления каждого выбранного имени файла в конце; общее количество вызовов команды будет намного меньше, чем количество совпавших файлов. ...
В дополнение к ответу Тердона,
-exec …
должен заканчиваться точкой с запятой ( ;
) или знаком плюс ( +
). Запятая специальный символ в оболочке (или, по крайней мере, каждый обстреливать я когда - либо использовал), поэтому, если он будет использоваться как часть find
команды , он должен быть экранирован или цитируемый ( \;
, ";"
или ';'
).При -exec … ;
этом {}
строка может появляться в команде любое количество раз, включая ноль , два или более, в любой позиции.
Посмотрите это
для примера того, почему вы можете обойтись -exec
без использования {}
.
Наличие двух или более матчей полезно главным образом потому, что в (по крайней мере) некоторые версии find
, то {}
не нужно быть слово само по себе; у него могут быть другие символы в начале или конце; например,
find . -type f -exec mv {} {}.bak ";"
С -exec … +
, {}
строка должна появиться как последний аргумент перед +
. Команда как
find . -name "*.bak" -exec mv {} backup_folder +
приводит к загадочному find: missing argument to ‘-exec’
сообщению об ошибке.
Обойти это именно специфичном для cp
и mv
команд
find . -name "*.bak" -exec mv -t backup_folder {} +
или
find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
{}
Должно быть слово само по себе; у него не может быть других символов в начале или конце. И, по крайней мере, в некоторых версиях у find
вас может быть не более одной версии {}
.
Примечание здравомыслия: Вы можете сказать
находить . -name "* .sh" -type f -executable -exec {} необязательные аргументы здесь ";"
запустить каждый из ваших скриптов. Но
находить . -name "* .sh" -type f -executable -exec {} +
запускает один из ваших скриптов с именами всех остальных в качестве параметров. Это похоже на высказывание
./*.sh
как команда оболочки, за исключением того find
, что она не гарантирует, что она сортирует свои результаты, поэтому вы не гарантированно работаете aaa.sh
(ваш *.sh
файл в алфавитном порядке ), как если бы вы работали ./*.sh
.
Аспект, find
который может быть не совсем понятен начинающим, заключается в том, что командная строка, по сути, является исполняемым оператором на тайном языке. Например,
find . -name "*.sh" -type f -executable -print
средства
for each file
if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
then
if it is a plain file (i.e., not a directory)
then
if it is executable (i.e., the appropriate `---x--x--x` bit is set)
then
print the file’s name
end if
end if
end if
end loop
или просто
for each file
if the file’s name matches `*.sh` AND it is a plain file AND it is executable
then
print the file’s name
end if
end loop
Некоторые -
ключевые слова являются одновременно исполняемым действием и тестом. В частности, это верно для -exec … ;
; например,
find . -type f -exec grep -q cat {} ";" -print
переводит на
для каждого файла если это простой файл (т.е. не каталог) тогда выполнить grep -q имя файла кошки если процесс завершится успешно (то есть выйдет со статусом 0) тогда напечатать имя файла конец, если конец, если конец цикла
который напечатает имена всех файлов, содержащих строку « cat
». И, хотя это то, что grep
может быть сделано само по себе (с опцией -l
(в нижнем регистре L
)), может быть полезно использовать его find
для поиска файлов, которые содержат определенную строку И имеют определенный размер И принадлежат определенному владельцу. И были изменены в определенный промежуток времени, ....
Однако это не работает для -exec … +
. Так как -exec … +
выполняет одну команду для нескольких файлов, нет смысла использовать ее как логическое условие внутри for each file …
цикла.
find
обычно выход завершается со статусом выхода 0, если вы не укажете ему недопустимые аргументы или он не встретит каталог, который он не может прочитать. Даже если выполняемая вами программа дает сбой (выходит с ненулевым состоянием выхода), она
find
завершится со статусом выхода 0.
За исключением случаев, если программа, с которой вы выполняете -exec … +
сбой (выходит с ненулевым состоянием выхода),
find
выйдет с ненулевым статусом выхода.В дополнение к миллиону версий find(1)
и тестированию того, что на find
самом деле происходит в паре систем, в
выпуске 7 Открытой группы базовых спецификаций, выпуск 2013 года, была
представлена некоторая информация о том find
, что должно, что можно, а что нельзя.
... -exec mv {} {}.bak ...
не гарантированно работает должным образом со всемиfind
реализациями. Стандартные состояния POSIX{}
должны отображаться в одиночку, чтобы их всегда можно было распознать, в противном случае поведение может оставить символы неизменными или заменить их путем. В первом случае вся ваша команда по существу удалит все файлы, кроме последнего найденного ...