Почему 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'


почему это? может кто-нибудь объяснить, что я делаю не так?

905   4  

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

    Ничего не найдено.