Préserver les extraits existants lorsqu’un lot échoue

ShellBeginner
Pratiquer maintenant

Introduction

Un pack d’écoute doit contenir tous les extraits demandés. Si une conversion échoue, un dossier partiel ne doit pas ressembler à un pack terminé. Vous améliorerez un script Bash pour préparer les fichiers en privé, s’arrêter honnêtement en cas d’erreur et publier uniquement lorsque toutes les conversions ont réussi.

Ce laboratoire possède ses propres enregistrements, une copie d’exercice endommagée et un ancien pack indépendant. Il n’utilise aucun fichier du laboratoire précédent. Terminez d’abord « Passer d’un extrait à un traitement par lots », ou maîtrisez ses guillemets, options FFmpeg, fonctions, tableaux et codes de sortie natifs. Vous utiliserez aussi trap de Bash pour nettoyer uniquement le répertoire temporaire appartenant au script.

Conserver les conversions incomplètes dans un espace privé

Dans cette étape, vous ferez en sorte qu’une conversion échouée ne laisse aucun lot publié, sans modifier le travail précédent.

Commencez dans Workspace, préparé pour les noms UTF-8. Revenez ici avec cd si un chemin relatif manque.

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

input contient les copies d’exercice de trois enregistrements. library contient les originaux intacts autorisés. archive/previous est un ancien pack à préserver ; notes.txt et scratch-other appartiennent à d’autres travaux. Modifiez uniquement vos scripts, les copies d’exercice et les nouveaux répertoires d’essais ou de sortie. Les entrées acceptées sont des fichiers ordinaires non cachés directement dans le répertoire d’entrée, avec l’extension .wav en minuscules : PCM mono signé sur 16 bits à 22050 Hz, durant au moins cinq secondes.

Lisez le script initial avec cat. Son exit 0 annonce un succès même après un échec de conversion, et son mkdir prématuré rend visible un pack incomplet.

cat batch.sh

L’essai suivant rencontre volontairement un enregistrement endommagé. Attendez-vous à une erreur FFmpeg se terminant par Invalid data found when processing input. Il s’agit d’un défaut de format de fichier, pas d’une commande manquante ni d’un problème réseau.

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

Il indique à tort Starter exit: 0. ls trial-pack ne montre que les conversions réussies ; la présence du dossier ne prouve pas qu’il est complet.

ls trial-pack

Supprimez uniquement cet essai jetable explicitement nommé. rm -r supprime récursivement un répertoire et son contenu ; -- termine l’analyse des options. Cette commande ne touche ni l’ancien pack, ni les originaux, ni les autres travaux.

rm -r -- trial-pack

Le contrat amélioré utilise un nouveau répertoire de sortie à chaque exécution. Les fichiers, répertoires et liens symboliques existants sont refusés, y compris les liens dont la cible manque. Le parent de la sortie doit exister, et la sortie doit être hors de l’entrée. Aucun processus d’écriture concurrent n’est pris en charge ; cette protection concerne les échecs de conversion, pas une transaction résistante aux arrêts brutaux ou coupures de courant.

Un répertoire de préparation contient les conversions avant publication. mktemp -d crée un répertoire privé au nom unique, en remplaçant le suffixe XXXXXX. Il est voisin de la sortie finale, afin que le déplacement final reste sur le même système de fichiers. trap '...' EXIT lance le nettoyage à la fin du script. Les guillemets simples reportent le développement de $stage jusqu’au nettoyage. rm -rf -- "$stage" supprime exactement ce répertoire propre au script ; ne le remplacez jamais par un motif comme /tmp/* ou .preview.*.

Les autres opérations de chemins explicitent ce contrat. $(command) capture du texte ; || exit 2 arrête l’exécution en cas d’échec. realpath -m normalise une cible qui n’existe pas encore, et dirname donne son parent. Le test de préfixe case "$output/" refuse une sortie à l’intérieur du répertoire d’entrée. Les guillemets du préfixe d’entrée préservent ses caractères littéraux, tandis que le * final recherche un suffixe. mv -T déplace la préparation vers le nom exact du nouveau répertoire au lieu de l’imbriquer dans un autre. Le test d’existence précédent n’est pas un verrou de concurrence.

Remplacez batch.sh par la version améliorée complète. Le tableau, l’extraction du nom, les guillemets et les arguments FFmpeg fonctionnent comme dans le premier laboratoire guidé.

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

Réessayez avec les mêmes entrées d’exercice endommagées. Cet échec est volontaire ; ne les réparez pas encore.

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

Vous devez obtenir Could not convert: zz Evening.wav et Protected batch exit: 1. La branche explicite arrête le lot. previews ne doit pas exister et le répertoire temporaire doit déjà avoir été supprimé.

ls -a inclut les noms cachés : vous pouvez donc rechercher des répertoires de préparation .preview. oubliés. Il doit toujours montrer scratch-other, dont le contenu doit rester inchangé.

ls -a

Lancez la vérification de cette étape. Elle teste votre script inchangé dans des répertoires jetables ; elle ne répare pas vos entrées et ne génère pas votre pack réel.

Restaurer la copie d’exercice et publier

Dans cette étape, vous diagnostiquerez l’enregistrement défectueux, restaurerez uniquement sa copie d’exercice autorisée et utiliserez votre script pour publier un pack complet.

Commencez dans Workspace. FFmpeg peut examiner un enregistrement sans produire un autre fichier multimédia : -f null - sélectionne une sortie nulle qui jette les échantillons décodés. Un décodage réussi confirme que le son est lisible ; un fichier endommagé renvoie une valeur différente de zéro. Nous l’utilisons uniquement sur la copie d’exercice nommée du cours.

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

Attendez une erreur de format et un code différent de zéro. Le fichier intact du même nom est disponible dans library. cp -- copie cet original par-dessus la copie endommagée ; les deux chemins entre guillemets désignent le fichier exact. Ne modifiez pas la bibliothèque elle-même.

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' "$?"

Le code doit maintenant être zéro. Si vous avez mal saisi le nom, consultez ls library et corrigez-le ; inutile de réinitialiser l’environnement. Exécutez le lot complet avec l’entrée restaurée.

bash batch.sh input previews 3

Vous devez voir Published 3 previews. Passez à Listening Room et rechargez la page. Écoutez chaque extrait sous Your listening pack, déplacez-vous dedans et téléchargez-en un. Chaque extrait doit durer trois secondes et commencer par son enregistrement correspondant. Cette page lit uniquement previews ; supprimer ou endommager un extrait ne peut pas lui faire jouer discrètement un original de la bibliothèque. Revenez à Workspace.

Enfin, essayez encore la sortie existante. Ce refus volontaire protège le pack complet.

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

Vous devez obtenir Output already exists et un code différent de zéro. Gardez cette sortie. Pour produire un autre pack plus tard, choisissez un nouveau nom et une durée de une à cinq secondes, avec son répertoire parent déjà présent. Les originaux, l’ancien pack, les notes et le répertoire sans rapport doivent rester inchangés.

Résumé

Vous avez séparé préparation et publication, signalé honnêtement les échecs et utilisé un trap EXIT pour nettoyer un seul répertoire propre au script. Vous avez diagnostiqué et restauré une copie audio endommagée, puis publié un pack complet et lisible en préservant le travail précédent. Le défi applique les mêmes outils à une autre collection.