find: Fehlendes Argument für "-exec" bei Verwendung der Suchform +

785
BeeOnRope

Ich möchte einen Befehl auf den Pfaden ausführen, die mit dem findBefehl gefunden wurden, und ich möchte +die Anzahl der Starts des externen Befehls reduzieren.

Kritisch hat der Befehl ein endgültiges Argument mit festem Wert. Hier ist ein konkretes Beispiel mit echoals Befehl, obwohl in der Realität:

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

Ich würde erwarten, dass dies gedruckt wird:

./fooA ./fooB second 

Stattdessen bekomme ich die Fehlermeldung 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\; `variant:

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

... aber das ist nicht das, was ich suche.

find --version Berichte:

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)  

Hier ist ein Auszug aus den Manpages zu den +und ;Formularen:

 -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
Welche Shell benutzt du? roaima vor 9 Jahren 0
Laut der Manpage erwartet der `-exec`-Befehl ganz am Ende des Ausdrucks das` {} `, da versucht wird, die gefundenen Dateien zu verketten. Wenn Sie den "zweiten" * vor den "{}" setzen, wird dies funktionieren, aber das hilft Ihnen natürlich nicht wirklich. Die Fehlermeldung ist etwas irreführend. Marcus Rickert vor 9 Jahren 0
Wo im Mann siehst du das? Ich habe die Mannausgabe in mein System aufgenommen. Für das `\;` Formular ist es klar, dass mehrere {} `erlaubt sind, was bedeutet, dass sie nicht am Ende des Befehls stehen müssen. Das "+" - Formular sagt "die Befehlszeile wird durch Anhängen jedes ausgewählten Dateinamens am Ende erstellt" - aber ich lese hier "das Ende" als das Ende der Zeichenfolge, die letztendlich verwendet wird, um das `{}` zu ersetzen. Wenn es immer am Ende war, warum {} verwenden? Der Text `Nur eine Instanz von {} ist innerhalb des Befehls zulässig.] Es ist möglich, dass eine Instanz an einer beliebigen Stelle vorhanden sein kann (oder warum sie nicht eingeschränkt wird). BeeOnRope vor 9 Jahren 0

2 Antworten auf die Frage

1
zackse

Ich konnte keine Lösung mit find -exec +oder finden find | xargs, aber GNU Parallel kann die Arbeit erledigen.

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

Produziert:

./fooA ./fooB second 

Beachten Sie, dass sich die -j1Option parallelauf jeweils einen Job beschränkt, der hier nur verwendet wird, um das Verhalten zu reproduzieren, von dem erwartet worden wäre find -exec +.

1
7yl4r

Hier ist eine ähnliche Lösung mit find | xargs:

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