Я хочу точно знать , что {} \;
и {} \+
и | xargs ...
делать. Пожалуйста, поясните это с пояснениями.
Ниже 3 команды запускаются и выводят тот же результат, но первая команда занимает немного времени, и формат также немного отличается.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
Это потому, что 1-й запускает file
команду для каждого файла, поступающего из find
команды. Итак, в основном это работает как:
file file1.txt
file file2.txt
Но последние 2 находят с помощью -exec
команд запустить команду файла один раз для всех файлов, как показано ниже:
file file1.txt file2.txt
Затем я запускаю следующие команды, первая из которых работает без проблем, а вторая дает сообщение об ошибке.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
Для команды с {} \+
он дает мне сообщение об ошибке
find: missing argument to `-exec'
это почему? может кто-нибудь объяснить, что я делаю не так?
Ответы:
Страница руководства (или онлайн-руководство по GNU ) почти все объясняет.
find -exec command {} \;
Для каждого результата
command {}
выполняется. Все вхождения{}
заменяются именем файла.;
перед ним стоит косая черта, чтобы оболочка не могла его интерпретировать.find -exec команда {} +
Каждый результат добавляется
command
и выполняется впоследствии. Принимая во внимание ограничения длины команды, я предполагаю, что эта команда может выполняться больше раз, при этом справочная страница поддерживает меня:Обратите внимание на эту цитату из справочной страницы:
Вот почему нельзя использовать символы между пробелами
{}
и+
за исключением пробелов.+
заставляет find определить, что аргументы должны быть добавлены к команде точно так же, какxargs
.Решение
К счастью, реализация GNU
mv
может принимать целевой каталог в качестве аргумента с любым-t
или более длинным параметром--target
. Его использование будет:Ваша
find
команда становится:На странице руководства:
источник
./test/
между{}
и+
, но между ними нельзя использовать символы, отличные от пробелов.+
AFAIU немного странная, так как она вставляет файлы «в конец» (а не вместо{}
), так зачем{}
вообще использовать - это сбивает с толку. Спасибо за-t
вариант, о котором я не знал, похоже, этот вариант был создан как обходной путь к этой-exec +
проблеме!Я столкнулся с той же проблемой в Mac OSX , используя оболочку ZSH : в этом случае нет
-t
возможностиmv
, поэтому мне пришлось найти другое решение. Однако следующая команда прошла успешно:Секрет заключался в том, чтобы процитировать подтяжки . Необязательно, чтобы фигурные скобки были в конце
exec
команды.Я тестировал под Ubuntu 14.04 (с оболочками BASH и ZSH ), он работает так же.
Однако при использовании
+
знака действительно кажется, что он должен стоять в концеexec
команды.источник
{}
потребности быть указаны вfish
иrc
оболочки, но неzsh
,bash
ни каких - либо других оболочек Bourne или CSH семей.bash
, действительно, кавычки не требуются. Любопытно, что у меня была проблема, если бы я не цитировал их под MacOS (используяzsh
). Но у меня нет Mac, чтобы попробовать еще раз ...Стандартный эквивалент
find -iname ... -exec mv -t dest {} +
дляfind
реализаций, которые не поддерживают,-iname
илиmv
реализаций, которые не поддерживают,-t
- использовать оболочку для изменения порядка аргументов:Используя
-name '*.[cC][pP][pP]'
, мы также избегаем зависимости от текущего языкового стандарта при выборе версии в верхнем регистреc
илиp
.Обратите внимание, что
+
, напротив,;
не является специальным в любой оболочке, поэтому его не нужно цитировать (хотя цитирование не повредит, за исключением, конечно, таких команд,rc
которые не поддерживают\
в качестве оператора цитирования).Волочить
/
в/dest/dir/
так чтоmv
завершается с ошибкой , вместо переименования ,foo.cpp
чтобы/dest/dir
в том случае , когда только одинcpp
был найден файл и/dest/dir
не существует или не является каталогом (или символическая ссылка на каталог).источник
источник
нет, разница между
+
и\;
должна быть обратной.+
добавляет файлы в конец команды exec, затем выполняет команду exec и\;
выполняет команду для каждого файла.Проблема в том,
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
чтоfind . -type f -iname '*.cpp' -exec mv {} ./test/ +
не нужно выходить из нее или прекращать+
xargs Я давно не использовал, но думаю работает как +.
источник
-name "*.cpp"
Я почти не использую -iname, если я не хочу выполнять какой-то сложный поиск по регулярным выражениям, например -iname '??? work. * \. Cpp'-iname
и-name
.-iname
является версией без учета регистра-name
и не имеет различий в обработке регулярных выражений. Я предлагаю попробовать команды перед публикацией, ваша команда также не работает в моей оболочке.