Copie todos os arquivos de uma pasta para outra quando não houver arquivo com o mesmo nome, mas uma extensão diferente existente

0

Eu tenho uma câmera IP que salva suas gravações no meu compartilhamento Samba. Eu quero copiar esses arquivos para um local diferente, uma vez que eles estão totalmente salvos.

Agora, meu problema é: a câmera leva algum tempo para copiar os arquivos em .avi format (denominado motion-date.avi ) para meu compartilhamento, enquanto isso também cria um arquivo .idx (denominado motion-date.idx ) do mesmo nome, que será apagado assim que for feito.

Por isso, quero copiar todos os arquivos .avi , que não têm um arquivo .idx correspondente, para uma pasta diferente.

    
por Gagootron 29.05.2017 / 09:10

1 resposta

1
find /source/dir/ -type f -name '*.avi' -exec sh -c 'f="{}"; test ! -f "${f%.*}.idx" && cp "$f" /target/dir/' \;

Este comando encontra todos os arquivos .avi sob o /source/dir/ e gera um shell básico para cada um. O shell então testa se não há um arquivo .idx correspondente e invoca cp quando necessário.

Edit: Eu mudei o comando um pouco para torná-lo mais infalível. Após a solicitação explícita, explico o comando inteiro com mais detalhes.

  • find - Encontre ...
  • /source/dir/ - ... em um determinado diretório ...
  • -type f - ... todos os arquivos ...
  • -name '*.avi' - ... com nomes correspondentes a este padrão ...
  • -exec - ... e para cada arquivo encontrado, execute ...
  • sh ... - ... um shell com seus próprios parâmetros (explicado posteriormente).
  • \; - indica onde o -exec termina. O truque importante é: cada string {} é substituída pelo caminho real para o arquivo específico encontrado; é assim que find -exec funciona.

Cada shell recebe a opção -c , que lhe diz para executar o próximo argumento como se fosse um comando digitado. O shell vê esse comando com {} já substituído pelo caminho do arquivo, conforme explicado acima.

E o comando é assim:

  • f="{}" - Memorize o caminho sob o nome f (lembre-se: neste momento já existe algum caminho em vez de {} ).
  • ; - separador de comandos.
  • test - Teste e retorne o status de saída de acordo; os argumentos a seguir dirão o que testar.
    • ! - Cuidado: o teste está invertido.
    • -f - Teste se há um arquivo existente ...
    • "${f%.*}.idx" - ... sob este caminho. A construção ${f%.*} informa ao shell para obter o conteúdo da variável f sem o fragmento do último ponto . para o final. Eu adiciono outra extensão. Desta forma eu os troco.
  • && - Apenas se o comando anterior (ou seja, test ) retornou o status de saída 0 ...
  • cp - ... copie ...
    • "$f" - ... o arquivo que foi encontrado por find ...
    • /target/dir/ - ... para o diretório de destino.

Notas finais:

  • Eu preciso de um shell para cuidar de "${f%.*}.idx" e && . Se eu quisesse copiar todos os arquivos encontrados, então ... -exec cp "{}" /target/dir/ \; seria suficiente (e ainda assim longe do ideal, mas não se distraia).
  • É bom citar (como em "" ) todos os caminhos que podem incluir espaços, caracteres especiais, etc.
  • O argumento (comando) para sh está entre aspas simples ( '' ). Se if foi colocado entre aspas duplas ( "" ), a expansão de "${f%.*}.idx" ocorreria no shell atual (aquele que executa find ) e isso não é o que eu quero. Você pode ler mais aqui .
por 29.05.2017 / 10:23

Tags