Existem erros em suas suposições, mas primeiro alguns antecedentes:
Você deve discernir dois usos de -exec
:
- com
\;
o{}
será substituído por um único item encontrado - com
+
o{}
será substituído por muitos itens (tantos quantos a linha de comando pode conter).
Portanto, seu exemplo de -exec
use invoca o comando cp
como itens encontrados por find
.
Usar find ... -exec cmd {} ... +
é semelhante em eficiência ao direcionar a saída de encontrar para um comando que lida com vários nomes de entrada.
Você também deve levar em conta que -exec
manipula bem nomes de arquivos / caminhos com espaços, mas quando você canaliza na saída de um outro programa que pode causar problemas. Portanto, alguns programas que esperam uma lista de nomes de arquivos de stdin podem ter uma opção para ter esses nomes de arquivos separados por NUL (geralmente -0
ou --null
). E o find
tem a opção de fornecê-los ao próximo programa, especificando: -print0
Agora vamos ao seu exemplo:
find . -type f -iname "*.cr2" | cp destination_directory
não copia os arquivos encontrados, pois o CP não lê a entrada padrão. Você teria que usar:
find . -type f -iname "*.cr2" | xargs cp -t destination_directory
ou para manipular os caminhos com espaços:
find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory
Com a mesma eficiência que você poderia fazer:
find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +
(Como o G-Man apontou, o {}
tem que ser no final, antes do +
)
Todos os itens acima fazem não construir a hierarquia sob o diretório de destino para isso e fora do hábito longo, mesmo se o diretório de origem é simples, eu me encontro usando cpio
:
find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory
que lista muito bem o que está fazendo ao longo do caminho.
As partes relevantes de man find
:
-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 encountered. 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 directory.
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 invoca‐
tions 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 command lines. Only one instance of '{}'
is allowed within the command. The command is executed in the
starting directory.