Relatório de erros de script de cópia CSV no bash

1

Eu tenho este script que copia os arquivos listados em um csv recursivamente a partir de uma pasta principal. O aspecto de cópia do script funciona perfeitamente. No entanto, agora quero adicionar algumas funcionalidades de detecção de erros. O loop "if" que eu adicionei abaixo não funciona como eu gostaria. Eu adicionei um arquivo falso à minha lista de csv para fins de teste, e o script relata que todos os arquivos foram copiados com sucesso, mesmo que um dos arquivos não exista. Alguém poderia sugerir como eu posso fazer o script reportar o (s) arquivo (s) que ele não encontrou / copiou com sucesso do csv e especificar os nomes dos arquivos? EDITAR ** Como existem mais de 4000 arquivos listados no CSV, gostaria que o script imprimisse um resumo de qualquer falha de cópia no final do script, em vez de cada arquivo copiado durante o processo. Isso tornaria mais fácil identificar / resumir quaisquer problemas.

while IFS=, read -r file rest
do
find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
done < $csv
if [ $? -eq 0 ]
then
echo "All files from CSV copied succesfully"
else "File from CSV not copied as not found"
fi
    
por neilH 29.02.2016 / 13:05

2 respostas

1

O código de erro retornado por find não tem nada a ver com a localização de arquivos. Ele só retornará um código de falha se o próprio comando não for executado. O que você está procurando é algo como:

while IFS=, read -r file rest
do
  find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || echo "File $file was not copied"
done < "$csv"
echo "Finished"

Dessa forma, o script informará sobre todos os arquivos que não foram copiados com êxito.

Se você quiser imprimir o erro apenas no final do script, poderá salvar os nomes de arquivo incorretos em uma variável e imprimi-lo após a conclusão do loop:

while IFS=, read -r file rest
do
  find "$sourcefolder" -name "$file" -exec cp '{}' "$destfolder" \;
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || badfiles=$(printf "%s\n%s" "$file" "$badfiles")
done < "$csv"

## Check if all the files were correctly copied
if [[ -z "$badfiles" ]]; then
        echo "All files were succesfuly copied."
else
        printf 'Some files were not copied:\n%s\n' "$badfiles"
fi

Você também pode estender isso para evitar a substituição de arquivos com o mesmo nome:

while IFS=, read -r file rest
do
  find "$sourcefolder" -name "$file" -print0 |
    while IFS= read -d '' -r filepath; do
     c="";
     while [[ -e "$destfolder/$file$c" ]]; do
       ((c++))
     done
     cp "$filepath" "$destfolder/$file$c"
  done
  ## Check if the file was copied
  [[ -e "$destfolder/$file" ]] || badfiles=$(printf "%s\n%s" "$file" "$badfiles")
done < "$csv"

## Check if all the files were correctly copied
if [[ -z "$badfiles" ]]; then
        echo "All files were succesfuly copied."
else
        printf 'Some files were not copied:\n%s\n' "$badfiles"
fi

Isso falhará se os nomes de arquivo em seu csv puderem conter novas linhas. Se isso for uma possibilidade, altere o primeiro loop while para:

while IFS= read -d"," -r file rest; do ...

Observe, no entanto, que isso falhará se qualquer linha do csv contiver apenas um nome de arquivo (portanto, sem vírgula). Você não pode ter as duas coisas, se você pode ter linhas sem vírgulas usar a primeira versão e se você pode ter nomes de arquivos com novas linhas, use o segundo.

    
por 29.02.2016 / 13:36
1
  1. Seu loop está incorreto, pois você não faz nada com rest

  2. Como terdon sugerido, verifique após cada cópia, em vez de uma vez após o ciclo

  3. Negue a existência de verificação de arquivo, para comentário correto
  4. E atente ao aviso de terdon, se você tiver os mesmos arquivos nomeados em sua árvore de fontes, só receberá um copiar no destino.

Tente isso,

while read -d, -r file
do
   find $sourcefolder -name "${file}" -exec cp '{}' $destfolder \;
   ## Check if the file was copied
   [[ ! -e "$destfolder/$file" ]] && echo "File $file was not copied"
done < "$csv"
echo "Finished"

Atualização:

Esta solução funciona se o seu CSV for assim

fileA,fileB,fileC,fileD, ...

No entanto, como você diz que a solução de terdon funciona, seu arquivo deve ficar assim

fileA,valueA1,valueA2,valueA3
fileB,valueB1,valueB2,valueB3
fileC,valueC1,valueC2,valueC3
fileD,valueD1,valueC2,valueD3

e o restante da linha após o nome do arquivo é simplesmente descartado.

    
por 29.02.2016 / 14:36