mv erro de comando “arquivo já existente”

3

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"

    
por Syed Moez 26.12.2014 / 20:54

2 respostas

3

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 {} \+
    
por 26.12.2014 / 21:05
2

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:

  1. Exclua os diretórios do espaço de pesquisa: 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 )
  2. 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.

    
por 26.12.2014 / 21:22

Tags