Aguarde o download de vários arquivos para concluir

4

Eu tenho o seguinte script que verifica se há um arquivo em uma pasta e se o arquivo é estável (isso é para o arquivo de vídeo grande que estou recebendo).

#!/bin/bash

cdate1=$(date +%Y%m%d-%T)
folder1="/path-to-folder"

cd $folder1

while file=$(ls "$folder1")
      [ -z "$file" ]
        do sleep 10
        done
            echo "There is a file in the folder at $cdate1"
            size1=$(stat -c '%s' "$file")
            echo "The size1 is $size1"
            sleep 30
            size2=$(stat -c '%s' "$file")
            echo "The size2 is $size2"
        if [ $size1 = $size2 ]
        then
            ls -l
            echo "Start converting"
        else 
            echo "Restart the script"
        fi

Como modificar o script para que ele possa verificar vários arquivos na mesma pasta e depois que todos eles estejam estáveis para iniciar o script de conversão?

    
por ispasov 18.09.2013 / 09:22

4 respostas

4

há vários problemas no seu script, começando com:

folder1="path-to-folder"
cd $folder1
while file=$(ls "$folder1") ...

isso realmente faz cd path-to-folder; ls path-to-folder ; se path-to-folder for absoluto (começando com um '/' como no seu exemplo), isso pode funcionar, mas não funcionará sempre que você usar caminhos relativos. Ele também não funcionará se path-to-folder contiver espaços, como você deve usar aspas em todos os lugares, por exemplo, cd "$folder1"

em seguida, fazer um while file=$(ls ...) fará um loop infinito, pois file sempre será definido como algo (o conteúdo do diretório).

a sintaxe apropriada seria for file in $(ls ...) , que parará de funcionar assim que você tiver nomes de arquivos com espaços (como o loop será executado em foo e bar se você tiver um arquivo chamado foo bar ). verifique por que você deve nunca analisar a saída de ls . em vez de usar ls você poderia simplesmente fazer for file in * .

finalmente, você pode ter arquivos que estão mudando, mesmo que o tamanho não esteja mais mudando.

uma boa maneira de iterar os arquivos é o comando find ; uma boa maneira de verificar se algo mudou é o mtime de um arquivo.

a seguinte função fornece um valor para a última modificação (mtime) de qualquer arquivo no diretório especificado

folder1="/path-to-folder"
find "${folder1}" -exec stat -c "%Y" \{\} \;    \
   | sort -n | tail -1

para que seu script se pareça com:

#!/bin/bash
dir="$1"
# check whether $dir exists
test -d "${dir}" || exit 1

last=0
current=1

while [ "$last" != "$current" ]; do
   last=$current
   current=$(find "${dir}" -exec stat -c "%Y" \{\} \; \
             | sort -n | tail -1)
   sleep 10
done
echo "directory is now stable..."

UPDATE

uma abordagem ainda melhor seria notificar ativamente o receptor de que um determinado arquivo foi transmitido. Uma solução muito simples seria também copiar um arquivo fictício vazio após a transmissão da carga útil. por exemplo. para um arquivo chamado foo.avi , copie outro arquivo foo.avi.copyfinished ; então você só precisa verificar a existência de foo.avi.copyfinished para ver que foo.avi está pronto.

while true; do
 for file_ready in *.copyfinished; do
   file=${file_ready%.copyfinished}
   if [ -e "${file}.converted" ]; then
      echo "skipping already converted file ${file}" 1>&2
   else
      touch "${file}.converted"
      do_convert "${file}"
   fi
 done
 sleep 1
done

esta solução obviamente requer a cooperação do lado do envio.

    
por 18.09.2013 / 11:08
2

É mais fácil controlar o processamento no lado de envio, onde o processo sabe se a transferência está concluída. Dessa forma, você também não receberá transferências canceladas.

Envie o arquivo para um nome ou diretório temporário. Quando o envio terminar, mova o arquivo para o local correto

cp srcvideo.avi /folder1/srcvideo.tmp && mv /folder1/srcvideo.tmp /folder1/srcvideo.avi

Então o seu script não precisa fazer todos os testes em tamanhos. Pode apenas esperar pelo arquivo correto.

cd /folder1 || exit 1
for file in *.avi; do
  echo "$file found"
  do_some_processing "$file"
done

Você pode conseguir o mesmo usando um diretório de transferência separado, sem alterar nomes de arquivos, se desejar.

    
por 18.09.2013 / 11:26
1

Esperar que os arquivos parem de crescer é uma maneira terrível de detectar se um download foi concluído. Se o download fizer uma pausa por muito tempo devido a uma falha de rede, seu script será acionado.

A melhor maneira de fazer algo após a conclusão de um download é instruir o programa de download a executar o script quando o download for concluído e bem-sucedido, ou aguardar até que o programa de download seja encerrado e executar o script se o download foi bem sucedido. Qualquer programa de download decente permitirá pelo menos uma dessas opções.

Se você estiver preso a algum método de download inferior, use um recurso de notificação para reagir quando o download do arquivo terminar, em vez de assistir manualmente o arquivo. No Linux, o recurso de notificação é inotify . Dependendo de como o programa de download funciona, reaja a um encerramento de arquivo (se o programa de download gravar diretamente no arquivo final) ou a uma renomeação (se o programa de download gravar primeiro em um arquivo temporário e o renomeie).

Você pode usar a ferramenta shell inotifywait para reagir quando um evento de arquivo ocorrer. Aqui está um exemplo que converte todos os arquivos renomeados.

cd /path/to/directory
inotifywait -m -e moved_to --format=%f . |
while IFS= read -r filename; do
  conversion-program "$filename"
done
    
por 19.09.2013 / 02:51
0

Se você quiser iniciar seu script antes de saber se todos os arquivos estão lá, a primeira coisa é verificar se o número de arquivos é constante. Você poderia fazer algo parecido usando listfile = $(ls "$folder")

[ $( echo $listfile | wc -w) != $(ls "$folder" | wc -w) ]

em um loop while; até que a coisa não seja igual, seu reset $listfile to $(ls "$folder") . Uma vez feito isso, você pode simplesmente fazer um do em $listfile , onde você faz exatamente o que estava fazendo em um arquivo; depois de concluído, você pode iniciar a conversão.

    
por 18.09.2013 / 10:39