find: отсутствует аргумент `-exec 'при использовании + формы find

792
BeeOnRope

Я хочу выполнить команду на путях, найденных с помощью findкоманды, и хочу использовать ее, +чтобы уменьшить количество запусков внешней команды.

Критически, команда имеет фиксированное значение конечного аргумента. Вот конкретный пример с echoкомандой как, хотя в реальном:

mkdir blah && cd blah touch fooA touch fooB find . -name 'foo*' -exec echo {} second + 

Я ожидал бы это напечатать:

./fooA ./fooB second 

но вместо этого я получаю ошибку find: missing argument to-exec ' . I've tried all sorts of permutations to get it to work with +. Why isn't this working? It works find with the\; `вариант:

find . -name 'foo*' -exec echo {} second \; ./fooB second ./fooA second 

... но это не то, что я после.

find --version доклады:

find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Written by Eric B. Decker, James Youngman, and Kevin Dalley. Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0)  

Вот выдержка из искусственных страниц, охватывающих +и ;формы:

 -exec command ; Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of `;' is encoun‐ tered. The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell. See the EXAMPLES section for examples of the use of the -exec option. The specified command is run once for each matched file. The command is executed in the starting direc‐ tory. There are unavoidable security problems surrounding use of the -exec action; you should use the -execdir option instead.  -exec command {} + This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its com‐ mand lines. Only one instance of `{}' is allowed within the command. The command is executed in the starting directory. 
3
Какую оболочку вы используете? roaima 9 лет назад 0
Согласно man-странице, команда `-exec` ожидает` {} `в самом конце выражения, так как она пытается объединить найденные файлы. Помещение `second` * перед *` {}} сработает, но, конечно, это не очень вам поможет. Сообщение об ошибке немного вводит в заблуждение. Marcus Rickert 9 лет назад 0
Где в человеке ты видишь это? Я включил вывод man в мою систему. Для формы `\;` ясно, что допускается несколько `{}`, что подразумевает, что они не должны быть в конце команды. Форма `+` говорит о том, что `командная строка создается путем добавления каждого выбранного имени файла в конце`, но здесь я читаю" конец "как конец строки, который в конечном итоге будет использован для замены` {}}. Если это всегда было в конце, зачем использовать {}? Текст `Только один экземпляр` {} 'разрешен в команде` подразумевает, что один экземпляр может быть где угодно (иначе почему бы не ограничить его)? BeeOnRope 9 лет назад 0

2 ответа на вопрос

1
zackse

I couldn't find a solution with find -exec + or find | xargs, but GNU Parallel can do the job.

mkdir blah && cd blah touch fooA touch fooB find . -name 'foo*' -print0 | parallel -0 -j1 -X echo {} second 

Produces:

./fooA ./fooB second 

Note, the -j1 option limits parallel to one job at a time, which is only used here in an attempt to reproduce the behavior that would have been expected from find -exec +.

1
7yl4r

Вот аналогичное решение с find | xargs:

find . -name 'foo*' -print0 | xargs -0 -n1 -I{} echo {} second 

Похожие вопросы