Использование точки с запятой (;) vs plus (+) с exec в find
Почему разница между использованием
find . -exec ls '{}' \+
и
find . -exec ls '{}' \;
Я получил:
$ find . -exec ls \{\} \+
./file1 ./file2
.:
file1 file2 testdir1
./testdir1:
testdir2
./testdir1/testdir2:
$ find . -exec ls \{\} \;
file1 file2 testdir1
testdir2
./file2
./file1
Ответы
Ответ 1
Это лучше всего проиллюстрировать на примере. Скажем, что find
отображает эти файлы:
file1
file2
file3
Используя -exec
с точкой с запятой (find . -exec ls '{}' \;
), выполните
ls file1
ls file2
ls file3
Но если вместо этого использовать знак плюса (find . -exec ls '{}' \+
), то как можно больше имен файлов передается в качестве аргументов для одной команды:
ls file1 file2 file3
Количество имен файлов ограничено максимальной длиной командной строки системы. Если команда превышает эту длину, команда будет вызываться несколько раз.
Ответ 2
Все ответы до сих пор верны. Я предлагаю это как более ясную (для меня) демонстрацию поведения, которое описывается с помощью echo
, а не ls
:
С точкой с запятой команда echo
вызывается один раз для каждого файла (или другого объекта файловой системы):
$ find . -name 'test*' -exec echo {} \;
./test.c
./test.cpp
./test.new
./test.php
./test.py
./test.sh
С плюсом команда echo
вызывается только один раз. Каждый найденный файл передается в качестве аргумента.
$ find . -name 'test*' -exec echo {} \+
./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh
Если find
отображает большое количество результатов, вы можете обнаружить, что команда называется дросселями по количеству аргументов.
Ответ 3
от человека
-exec команда;
Выполнить команду; true, если возвращается 0. Все следующие аргументы для поиска считаются аргументами команды до тех пор, пока аргумент, состоящий из ';' встречается. Струна '{}' заменяется текущим именем файла, обрабатываемым повсюду это происходит в аргументах команды, а не только в аргументах где он один, как в некоторых версиях находки. Оба из них может потребоваться экранирование конструкций (с помощью "\" ) или защитить их от расширения оболочкой. См. ПРИМЕРЫ sec- для примера использования опции "-exec". Специфические Команда fied запускается один раз для каждого сопоставленного файла. Команда выполняется в стартовом каталоге. Неизбежно проблемы безопасности, связанные с использованием опции -exec; вы вместо этого следует использовать опцию -execdir.
-exec command {} + Этот вариант опции -exec выполняет указанную команду на выбранные файлы, но командная строка построена путем добавления каждое имя выбранного файла в конце; общее число invoca- команда команды будет намного меньше, чем количество согласованные файлы. Командная строка построена почти так же что xargs строит свои командные строки. Только один экземпляр '{}' разрешено внутри команды. Команда выполняется в стартовый каталог.
так, как я его понимаю; \; выполняет отдельные команды и + добавляет каждое имя. его в основном способ, которым он выполняется, поскольку\является побегом, поэтому его
ls testdir1; ls testdir2
против
ls testdir1 testdir2
Выполнение вышеуказанного в моей оболочке отразило вывод вашего вопроса.
ОБНОВЛЕНИЕ 2
Итак, зачем вы хотите использовать +
скажем, у меня есть два файла: 1.tmp и 2.tmp
1.tmp:
1
2
3
2.tmp:
0
2
3
работает
find *.tmp -exec diff {} \;
> diff: missing operand after `1.tmp'
> diff: Try `diff --help' for more information.
> diff: missing operand after `2.tmp'
> diff: Try `diff --help' for more information.
если вы используете + и объединяете результаты поиска так:
find *.tmp -exec diff {} \+
1c1,3
< 1
---
> 0
> 2
> 30
поэтому в этом случае его разность между diff 1.tmp; diff 2.tmp и diff 1.tmp 2.tmp
Есть случаи, когда \; подходит и + будет необходимо. использование + с rm является одним из таких экземпляров, где, если вы удаляете большое количество файлов, скорость которых значительно улучшилась; Мне всегда нравится больше узнать о поиске, это такой мощный и удобный инструмент, я надеюсь, что этого достаточно, чтобы объяснить различия.
Ответ 4
Здесь сделка: find имеет специальный синтаксис. Вы используете {}
так, как они есть, потому что они имеют смысл находить в качестве пути к найденному файлу, и (большинство) оболочек не интерпретируют их иначе. Вам нужна обратная косая черта \;
, потому что точка с запятой имеет смысл для оболочки, которая ест ее, прежде чем find сможет ее получить. Итак, какая находка хочет видеть ПОСЛЕ оболочки, в списке аргументов, переданных программе C, есть
"- exec", "rm", "{}", ";"
но вам нужно \;
в командной строке, чтобы получить точку с запятой через оболочку для аргументов.
Вы можете уйти с помощью \{\}
, потому что интерпретация текста \{\}
с оболочкой называется просто {}
. Аналогично, вы можете использовать '{}'.
То, что вы не можете сделать, это использовать
-exec 'rm {} ;'
потому что оболочка интерпретирует это как один аргумент,
"- exec", "rm {};"
и "rm {};" это не имя команды. (По крайней мере, если кто-то действительно не притворяется.)
Обновление
разница между
$ ls file1
$ ls file2
и
$ ls file1 file2
Символ + связывает имена в командной строке.
Ответ 5
Разница между ;
(точкой с запятой) или +
(плюс знак) заключается в том, как аргументы передаются в параметр find -exec
/-execdir
. Например:
-
с помощью ;
будет выполняться несколько команд (отдельно для каждого аргумента),
Пример:
$ find /etc/rc* -exec echo Arg: {} ';'
Arg: /etc/rc.common
Arg: /etc/rc.common~previous
Arg: /etc/rc.local
Arg: /etc/rc.netboot
Все следующие аргументы find
считаются аргументами команды.
Строка {}
заменяется текущим именем файла, который обрабатывается.
-
с помощью +
будут выполняться наименьшие возможные команды (по мере объединения аргументов). Это очень похоже на то, как работает команда xargs
, поэтому она будет использовать как можно больше аргументов для каждой команды, чтобы избежать превышения максимального предела аргументов на строку.
Пример:
$ find /etc/rc* -exec echo Arg: {} '+'
Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot
Командная строка создается путем добавления каждого имени выбранного файла в конце.
Внутри команды допускается только один экземпляр {}
.
См. также:
Ответ 6
мы пытались найти файл для домашнего хозяйства.
найти. -exec echo {} \; команда побежала за ночь, в итоге не получилось.
найти. -exec echo {}\+ имеет результаты и занимает всего несколько часов.
Надеюсь, что это поможет.