Почему find-exec mv {}./целевой/ + не работают?
я хочу точно знать, что {} ; и {} + и | xargs ... do. Просьба разъяснить это с помощью пояснений.
ниже 3 команды запускаются и выводят тот же результат, но первая команда занимает немного времени, и формат также немного отличается.
find . -type f -exec file {} ;
find . -type f -exec file {} +
find . -type f | xargs file
это потому, что 1-ый работает file команда для каждого файла, поступающего из . Итак, в основном он работает как:
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'
почему это? может кто-нибудь объяснить, что я делаю не так?
4 ответов:
The страница руководства (или онлайн руководство GNU) в значительной степени объясняет все.
команда find-exec {} \;
для каждого результата,
command {}выполняется. Все случаи{}заменяются именем.;имеет префикс с косой чертой, чтобы предотвратить оболочку от интерпретации его.команда find-exec {} +
каждый результат добавляется к
commandи впоследствии казнен. Принимая принимая во внимание ограничения длины команды, я предполагаю, что эта команда может выполняться больше раз, при этом ручная страница поддерживает меня:общее количество вызовов команды будет намного меньше, чем количество совпадающих файлов.
обратите внимание на эту цитату из руководства страницы:
командная строка построена во многом так же, как xargs строит свои командные строки
вот почему нет персонажей допускаются между
{}и+за исключением пробелов.+делает find обнаружить, что аргументы должны быть добавлены к команде так же, какxargs.решение
к счастью, реализация GNU
mvможно принять целевой каталог в качестве аргумента, либо-tили более длинный параметр--target. Это использование будет:mv -t target file1 file2 ...код будет:
find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+
от руководство по эксплуатации страницы:
- команда exec;
выполнить команду; true, если возвращается 0 статус. Все следующие найденные аргументы считаются аргументами команды до тех пор, пока не будет найден аргумент, состоящий из`;'. Строка "{} " заменяется текущим именем файла, обрабатываемым везде, где он встречается в аргументах команды, а не только в аргументах, где он находится один, как в некоторых версиях find. Обе эти конструкции могут потребоваться быть экранированы (С `\') или в кавычках, чтобы защитить их от расширения оболочкой. Примеры использования параметра-exec см. В разделе Примеры. Указанная команда выполняется один раз для каждого сопоставленного файла. Команда выполняется в стартовом каталоге. Существуют неизбежные проблемы безопасности, связанные с использованием действия-exec; вместо этого следует использовать параметр-execdir.
- exec command {} +
этот вариант действия-exec запускает указанную команду для выбранных файлов, но командная строка строится путем добавления каждого выбранного имени файла в конце; общее количество вызовов команды будет гораздо меньше, чем количество совпавших файлов. Командная строка построена во многом так же, как xargs строит свои командные строки. В команде допускается только один экземпляр ` {}'. Команда выполняется в стартовом каталоге.
я столкнулся с той же проблемой на Mac OSX, С помощью ZSH оболочка: в этом случае нет на
mv, поэтому мне пришлось найти другое решение. Однако следующая команда удалась:find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;секрет чтобы процитировать фигурные скобки. Нет необходимости для фигурных скобок, чтобы быть в конце .
Я тестировал под Ubuntu 14.04 (С Баш и ZSH снарядов), он работает так же.
однако, при использовании
+знак, кажется, действительно, что он должен быть в конце .
стандартный эквивалент
find -iname ... -exec mv -t dest {} +наfindреализации, которые не поддерживают-inameилиmvреализации, которые не поддерживают-tиспользовать оболочку для изменения порядка аргументов:find . -name '*.[cC][pP][pP]' -type f -exec sh -c ' exec mv "$@" /dest/dir/' sh {} +С помощью
-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 я не использовал в течение длительного времени, но я думаю, что работает как +.
Comments