Você deve evitar a pesquisa no diretório de destino. Então você pode adicionar ! -path $TARGET_DIR
como por exemplo:
find . -name '*.template' ! -path "*3DBGB_run/*" -exec mv -it ./3DBGB_run {} \+
Estou usando um script simples para criar alguns diretórios. Encontrar alguns arquivos específicos por nome e, em seguida, movê-los para os diretórios que criei. O código que estou usando está abaixo:
mkdir ./3DBGB_run
mkdir ./run_optimization
mkdir ./run_optimization/project_mesh
mkdir ./run_optimization/CFD_optimized
find . -name '*.template' -exec mv -i {} ./3DBGB_run \;
find . -name '3dbgbinput.*.dat' -exec mv -i {} ./3DBGB_run \;
find . -name 'controlinputs.*.dat' -exec mv -i {} ./3DBGB_run \;
find . -name '*.iec' -exec mv -i {} ./run_optimization/project_mesh \;
find . -name '*.trb' -exec mv -i {} ./run_optimization/project_mesh \;
find . -name '*.py' -exec mv -i {} ./run_optimization \;**
O código é executado e move os arquivos para os diretórios desejados, mas também exibe uma mensagem de erro para cada arquivo que "não pode mover o arquivo porque é o mesmo arquivo"
find
está localizando seus arquivos duas vezes: no lugar onde eles começaram e para onde você os moveu. Isso significa que acaba funcionando:
mv -i 3DBGB_run/x.template 3DBGB_run/x.template
e produz o erro que você vê.
find
vê os arquivos "ao vivo" da maneira como estão - ele não cria uma lista com antecedência e, em seguida, executa o comando para tudo na lista. A ordem em que olha os arquivos e diretórios é indefinida (é provável que venha do sistema de arquivos), portanto, isso acontecerá para todos os arquivos examinados antes do diretório em que você os move.
Como find
não sabe o que você está fazendo no -exec
, ele não pode compensar isso. Você pode fazer algumas coisas sobre isso:
find . -name '*.template' -path "./3DBGB_run" -prune -o -exec mv -i {} ./3DBGB_run \;
. A parte -path
corresponde ao diretório no qual você está movendo as coisas e -prune
exclui a árvore inteira da recursão. -o
faz com que o restante do comando (seu original -exec
) seja executado no restante do tempo. O comando nunca é executado em arquivos dentro do diretório. (Este é um exemplo explícito no manual de GNU find
) Construa a lista antes da mudança. Isso pode ser melhor em algumas circunstâncias, mas se seus nomes de arquivos tiverem espaços ou outros IFS
personagens, então não funciona tão bem. Se isso não se aplica, algo como:
files=$(find . -name '*.template')
mv "${files[@]}" 3DBGB_run
também funcionará.
Quando você estiver usando find -exec
, terminar o comando com +
em vez de ;
fará com que find
execute o número mínimo de comandos, coletando vários argumentos em cada execução, o que é mais eficiente. Às vezes isso não funciona para um comando em particular, mas estaria bem aqui. Se este for um comando único, isso realmente não importa, mas se você executá-lo muito, os processos de salvamento economizarão tempo.