Proteja as prévias existentes quando um lote falhar

ShellBeginner
Pratique Agora

Introdução

Um pacote de escuta deve conter todas as prévias solicitadas. Se uma conversão falhar, uma pasta parcial não deve parecer um pacote concluído. Você melhorará um script Bash para preparar arquivos de forma privada, parar corretamente em caso de erro e publicar somente quando todas as conversões tiverem sucesso.

Este laboratório começa com suas próprias gravações, uma cópia de prática danificada e um pacote antigo independente. Não usa arquivos do laboratório anterior. Conclua primeiro “Transforme uma prévia em um lote” ou conheça suas aspas, opções FFmpeg, funções, arrays e códigos de saída dos próprios comandos. Você também usará trap do Bash para limpar somente o diretório temporário do próprio script.

Mantenha conversões incompletas fora da publicação

Nesta etapa, você fará com que uma conversão malsucedida não publique um novo lote, mantendo inalterado o trabalho anterior.

Comece em Workspace, preparado para nomes UTF-8. Volte aqui com cd se um caminho relativo estiver faltando.

cd /home/labex/project/audio-studio
ls input library archive/previous

input contém cópias de prática de três gravações. library contém os originais intactos permitidos. archive/previous é um pacote antigo que deve ser preservado; notes.txt e scratch-other pertencem a outros trabalhos. Altere apenas seus scripts, as cópias de prática e novos diretórios de experimento ou saída. As entradas suportadas são arquivos regulares não ocultos diretamente no diretório de entrada, com extensão .wav em minúsculas: PCM mono de 16 bits com sinal a 22050 Hz e pelo menos cinco segundos de duração.

Leia o script inicial com cat. Seu exit 0 informa sucesso mesmo após uma falha de conversão, e seu mkdir antecipado deixa visível um pacote incompleto.

cat batch.sh

A tentativa seguinte encontra intencionalmente uma gravação danificada. Espere um erro FFmpeg terminado em Invalid data found when processing input. Isso é falha de formato de arquivo, não um comando ausente ou problema de rede.

bash batch.sh input trial-pack 3
printf 'Starter exit: %s\n' "$?"

Ele informa enganosamente Starter exit: 0. ls trial-pack mostra somente as conversões bem-sucedidas; a pasta, por si só, não prova completude.

ls trial-pack

Remova apenas esse teste descartável com nome explícito. rm -r remove recursivamente um diretório e seu conteúdo; -- termina a interpretação de opções. O comando não toca no pacote antigo, nos originais ou no trabalho sem relação.

rm -r -- trial-pack

O contrato melhorado usa um diretório de saída novo em cada execução. Arquivos, diretórios e links simbólicos existentes são recusados, inclusive links sem destino existente. O pai da saída deve existir e a saída deve estar fora da entrada. Processos de escrita concorrentes não são suportados. A proteção se refere a falhas de conversão, não a uma garantia transacional contra encerramento abrupto ou queda de energia.

Um diretório de preparação guarda conversões antes da publicação. mktemp -d cria um diretório privado de nome único, substituindo o sufixo XXXXXX. Ele fica ao lado da saída final para que o último movimento permaneça no mesmo sistema de arquivos. trap '...' EXIT executa a limpeza quando o script termina. Aspas simples adiam a expansão de $stage até a limpeza. rm -rf -- "$stage" remove exatamente esse diretório próprio; nunca o substitua por um curinga como /tmp/* ou .preview.*.

As outras operações de caminho tornam o contrato explícito. $(command) captura texto; || exit 2 para em caso de falha. realpath -m normaliza um destino que ainda não existe e dirname obtém seu pai. O teste de prefixo case "$output/" recusa uma saída dentro do diretório de entrada. Colocar o prefixo de entrada entre aspas mantém seus caracteres literais, enquanto o * final corresponde a um sufixo. mv -T move a preparação para o nome exato do novo diretório, em vez de colocá-la dentro de outro. A verificação anterior de existência não é um bloqueio de concorrência.

Substitua batch.sh pela versão melhorada completa. O array, a extração do nome, as aspas e os argumentos FFmpeg funcionam como no primeiro laboratório guiado.

cat > batch.sh <<'BASH'
#!/usr/bin/env bash
if [ "$#" -ne 3 ]; then printf 'Usage: batch.sh INPUT OUTPUT SECONDS\n' >&2; exit 2; fi
case "$3" in 1|2|3|4|5) seconds=$3 ;; *) printf 'Use 1 to 5 seconds\n' >&2; exit 2 ;; esac
if [ ! -d "$1" ]; then printf 'Input directory missing\n' >&2; exit 2; fi
if [ -e "$2" ] || [ -L "$2" ]; then printf 'Output already exists\n' >&2; exit 2; fi
input=$(realpath -- "$1") || exit 2
output=$(realpath -m -- "$2") || exit 2
parent=$(dirname -- "$output")
if [ ! -d "$parent" ]; then printf 'Output parent missing\n' >&2; exit 2; fi
case "$output/" in "$input/"*) printf 'Output must be outside input\n' >&2; exit 2 ;; esac
shopt -s nullglob
files=("$input"/*.wav)
if [ "${#files[@]}" -eq 0 ]; then printf 'No WAV inputs\n' >&2; exit 1; fi
stage=$(mktemp -d "$parent/.preview.XXXXXX") || exit 1
trap 'rm -rf -- "$stage"' EXIT
for source in "${files[@]}"; do
  name=${source##*/}
  if ! ffmpeg -nostdin -v error -i "$source" -t "$seconds" -c:a pcm_s16le "$stage/$name"; then
    printf 'Could not convert: %s\n' "$name" >&2
    exit 1
  fi
done
if ! mv -T -- "$stage" "$output"; then exit 1; fi
printf 'Published %s previews\n' "${#files[@]}"
BASH

Tente novamente as mesmas entradas de prática danificadas. A falha é intencional; ainda não as repare.

bash batch.sh input previews 3
printf 'Protected batch exit: %s\n' "$?"

O esperado é Could not convert: zz Evening.wav e Protected batch exit: 1. O ramo explícito interrompe o lote. previews não deve existir e o diretório temporário de preparação já deve ter sido removido.

ls -a inclui nomes ocultos, permitindo procurar diretórios de preparação .preview. abandonados. Ele ainda deve mostrar scratch-other, cujo conteúdo deve continuar inalterado.

ls -a

Execute a verificação da etapa. Ela testa seu script sem modificações em diretórios descartáveis; não repara as entradas de prática nem gera seu pacote real.

Restaure a cópia de prática e publique o lote

Nesta etapa, você diagnosticará a gravação defeituosa, restaurará somente sua cópia de prática permitida e usará o script para publicar um pacote completo.

Comece em Workspace. O FFmpeg pode inspecionar uma gravação sem produzir outro arquivo de mídia: -f null - escolhe uma saída nula que descarta as amostras decodificadas. A decodificação bem-sucedida confirma áudio legível; um arquivo danificado retorna um valor diferente de zero. Usaremos isso somente na cópia de prática nomeada do curso.

ffmpeg -nostdin -v error -i "input/zz Evening.wav" -f null -
printf 'Decode exit: %s\n' "$?"

Espere um erro de formato e um código diferente de zero. O arquivo intacto com o mesmo nome está em library. cp -- copia esse original sobre a cópia de prática danificada; os dois caminhos entre aspas identificam o arquivo exato. Não altere a biblioteca em si.

cp -- "library/zz Evening.wav" "input/zz Evening.wav"
ffmpeg -nostdin -v error -i "input/zz Evening.wav" -f null -
printf 'Decode exit: %s\n' "$?"

Agora espere zero. Se digitou o nome errado, consulte ls library e corrija; não é preciso reiniciar o ambiente. Execute o lote completo com a entrada restaurada.

bash batch.sh input previews 3

O esperado é Published 3 previews. Mude para Listening Room e recarregue. Reproduza cada clipe em Your listening pack, mude de posição e baixe um. Cada clipe deve durar três segundos e começar com a gravação correspondente. A página lê apenas previews; excluir ou danificar uma prévia não faz com que ela reproduza silenciosamente um original da biblioteca. Volte a Workspace.

Por fim, tente usar a saída existente outra vez. Essa recusa intencional protege o pacote completo.

bash batch.sh input previews 3
printf 'Existing output exit: %s\n' "$?"

O esperado é Output already exists e um código diferente de zero. Mantenha essa saída. Para outro pacote no futuro, escolha um nome novo e uma duração de um a cinco segundos, com o diretório pai já presente. As gravações originais, o pacote antigo, as notas e o diretório independente devem continuar inalterados.

Resumo

Você separou preparação e publicação, retornou as falhas corretamente e usou um trap EXIT para limpar um único diretório próprio. Diagnosticou e restaurou uma gravação de prática danificada e publicou um pacote completo com áudio que pode ser reproduzido, preservando o trabalho anterior. O desafio aplica as mesmas ferramentas a outra coleção.