Linux / Commande dd : copier des blocs, extraire une région et vérifier le résultat

dd copie des octets d’une entrée vers une sortie, avec un contrôle des blocs, des décalages et de certaines conversions. Utilisez if= pour l’entrée et of= pour la sortie ; une erreur sur of peut écraser des données immédiatement, et une copie réussie ne garantit pas à elle seule la cohérence d’une image de système en activité.

Pour copier des fichiers et dossiers ordinaires avec leurs attributs, cp est souvent plus direct. dd est utile lorsque vous devez copier un flux brut, sélectionner une région précise ou produire une image, en connaissant les limites du format et du support.

Lire correctement les opérandes de dd

La plupart des réglages s’écrivent sous la forme nom=valeur, sans espaces autour du signe égal. Sans if, dd lit l’entrée standard ; sans of, il écrit sur la sortie standard. Un fichier donné avec of est normalement tronqué avant la copie, sauf choix approprié de conversion.

Opérande Rôle Condition à vérifier
if=CHEMIN Entrée lue Source correcte, lisible et stable
of=CHEMIN Sortie écrite Cible correcte et politique d’écrasement explicite
bs=N Taille des blocs d’entrée et de sortie Ne décrit ni le secteur matériel ni le bloc du système de fichiers
count=N Limite du nombre de blocs d’entrée lus Une fin de fichier ou des lectures courtes peuvent réduire la quantité copiée
skip=N Décalage dans l’entrée Unité liée à ibs, ou à bs si bs le définit
seek=N Décalage dans la sortie Unité liée à obs, ou à bs si bs le définit

Les réglages séparés ibs et obs concernent respectivement les blocs d’entrée et de sortie. Évitez les opérandes numériques répétés : une commande courte avec une seule définition de chaque taille est plus simple à vérifier.

dd if="source avec espace.bin" of="nouvelle copie.bin" bs=1M conv=excl status=progress

Les guillemets appartiennent à la syntaxe du shell. Dans if="$source", un nom commençant par un tiret fait déjà partie de la valeur de if ; il n’est pas un argument fichier libre à déplacer après -- comme avec cp. Les options autonomes GNU documentées sont --help et --version ; les réglages de copie utilisent les opérandes.

Essayer une copie vérifiable sur douze octets

Ces commandes créent un nouvel espace temporaire et deux petits fichiers. Elles ne demandent pas de privilèges et ne visent aucun périphérique :

espace=$(mktemp -d) || exit 1
printf 'ABCDEFGHIJKL' > "$espace/source.bin"
dd if="$espace/source.bin" of="$espace/copie.bin" bs=4 conv=excl status=none || exit 1
cmp -- "$espace/source.bin" "$espace/copie.bin" || exit 1
wc -c < "$espace/copie.bin"
printf 'Copie identique ; espace : %s\n' "$espace"

Le résultat de wc est 12. cmp reste silencieux lorsqu’il trouve les mêmes octets, puis le message confirme la comparaison. conv=excl refuse de réutiliser une sortie existante : si vous répétez seulement la ligne dd avec la même copie.bin, l’appel échoue au lieu de l’écraser.

Pour refaire tout l’essai, repartez de la première ligne afin d’obtenir un autre espace temporaire. Inspectez les chemins affichés avant le nettoyage. Les commandes suivantes réutilisent la variable espace et les fichiers de cet essai.

Choisir la taille des blocs et comprendre count

Dans GNU dd, 1K vaut 1 024 octets et 1M vaut 1 048 576 octets ; 1MB vaut 1 000 000 octets. La notation 1MiB exprime aussi 1 048 576 octets. Les règles GNU sur les suffixes de taille permettent de lever cette ambiguïté.

dd if="$espace/source.bin" of="$espace/limite.bin" bs=4 count=2 conv=excl status=none
wc -c < "$espace/limite.bin"
dd if="$espace/source.bin" of="$espace/fin.bin" bs=4 count=4 conv=excl status=none
wc -c < "$espace/fin.bin"

La première sortie contient 8 octets, ABCDEFGH. La seconde en contient 12, pas 16 : l’entrée s’arrête après trois blocs. count fixe une limite et ne fabrique pas automatiquement des données pour atteindre une taille cible.

Avec un pipe, une lecture peut retourner moins d’octets que la taille demandée, même si le flux n’est pas terminé. iflag=fullblock accumule les lectures pour que count porte sur des blocs complets autant que l’entrée le permet.

set -o pipefail
cat -- "$espace/source.bin" |
  dd of="$espace/depuis-pipe.bin" bs=4 count=2 iflag=fullblock conv=excl status=none
wc -c < "$espace/depuis-pipe.bin"

Cette entrée contient assez de données pour produire 8 octets. fullblock ne crée pas les octets absents à la fin du flux. pipefail permet de détecter aussi une erreur du producteur ; pour un producteur beaucoup plus long que la limite de dd, prévoyez également le cas où celui-ci rencontre une fermeture anticipée du pipe.

Une taille de quelques mégaoctets peut convenir à une copie volumineuse, mais « plus grand » n’est pas une garantie de débit supérieur. Les caches, le support, le transport et les erreurs changent le résultat. Un débit affiché sur une petite copie en cache ne mesure pas à lui seul la vitesse durable du stockage.

Extraire une région et modifier une copie existante

dd if="$espace/source.bin" of="$espace/region.bin" bs=4 skip=1 count=2 conv=excl status=none
printf 'EFGHIJKL' > "$espace/region-attendue.bin"
cmp -- "$espace/region-attendue.bin" "$espace/region.bin"

skip=1 saute ici un bloc de 4 octets ; count=2 copie les 8 octets suivants. Si vous changez bs, vous changez aussi le sens de ces nombres. Sur une version GNU qui le prend en charge, le suffixe B appliqué à skip ou count exprime directement un nombre d’octets :

dd if="$espace/source.bin" of="$espace/cinq-octets.bin" bs=4 skip=2B count=5B conv=excl status=none
printf 'CDEFG' > "$espace/cinq-attendus.bin"
cmp -- "$espace/cinq-attendus.bin" "$espace/cinq-octets.bin"

La région copiée commence au décalage 2, en comptant le premier octet au décalage 0, et contient 5 octets. Ces suffixes sont des extensions GNU ; contrôlez leur prise en charge dans l’aide locale avant de porter la commande. Une version ancienne qui refuse 2B peut effectuer ce petit essai avec bs=1 : skip et count sont alors des nombres de blocs d’un octet.

dd if="$espace/source.bin" of="$espace/cinq-compatibles.bin" bs=1 skip=2 count=5 conv=excl status=none
printf 'CDEFG' > "$espace/cinq-compatibles-attendus.bin"
cmp -- "$espace/cinq-compatibles-attendus.bin" "$espace/cinq-compatibles.bin"

Pour modifier une région d’une sortie existante, la préservation du reste du fichier doit être explicite. L’essai suivant ne touche qu’un nouveau fichier de démonstration :

printf 'abcdefghij' > "$espace/modifiable.bin"
printf 'XY' > "$espace/modification.bin"
dd if="$espace/modification.bin" of="$espace/modifiable.bin" bs=1 seek=3 conv=nocreat,notrunc status=none || exit 1
printf 'abcXYfghij' > "$espace/attendu.bin"
cmp -- "$espace/attendu.bin" "$espace/modifiable.bin" || exit 1
wc -c < "$espace/modifiable.bin"

seek=3 avec bs=1 commence l’écriture au quatrième octet. La sortie reste longue de 10 octets et vaut abcXYfghij. conv=nocreat exige que la sortie existe déjà ; conv=notrunc préserve les données en dehors de la zone réécrite. notrunc n’empêche pas l’écrasement de cette zone et ne rend pas une modification atomique.

Sans notrunc, seek ne protège pas la fin du fichier : la sortie peut être tronquée au décalage choisi avant l’écriture. Effectuez ce type d’opération sur une copie vérifiée et gardez l’original jusqu’à la validation du résultat.

Distinguer remplissage, synchronisation et progression

Réglage Effet Confusion à éviter
conv=sync Complète les blocs d’entrée courts, normalement avec des octets nuls Ce n’est pas une demande de vidage des caches
conv=fsync Demande la synchronisation des données et métadonnées de sortie avant de terminer Ne compare pas les octets et ne rend pas l’entrée cohérente
conv=fdatasync Demande la synchronisation des données de sortie avant de terminer Ne correspond pas au remplissage conv=sync
status=progress Affiche les informations de transfert sur l’erreur standard Une ligne d’avancement n’est pas un résultat final de vérification
status=none Masque les informations et avertissements de transfert Les erreurs restent signalées

La demande fsync est traitée selon les garanties du système et du stockage ; elle ne remplace ni le contrôle d’erreur ni une stratégie de sauvegarde. Le réglage oflag=sync demande une synchronisation à chaque écriture et peut avoir un coût différent de la synchronisation finale. Évitez de le choisir uniquement à cause de la ressemblance du nom.

Pour un test limité d’écriture de zéros, vous pouvez créer 8 Kio, soit 8 192 octets :

dd if=/dev/zero of="$espace/zeros.bin" bs=1K count=8 conv=excl status=none
wc -c < "$espace/zeros.bin"

Cette commande écrit un flux de zéros. La taille allouée peut dépendre du système de fichiers, de la compression ou d’autres mécanismes du stockage ; ne déduisez pas une allocation physique exacte de la seule taille logique. conv=sparse demande au contraire de sauter certains blocs nuls sur une sortie adaptée. Ne l’utilisez pas aveuglément avec notrunc : des données non nulles déjà présentes dans les zones sautées peuvent rester intactes.

Copier un fichier avec refus d’écrasement et comparaison

Enregistrez ce script complet sous copier-dd.sh, puis exécutez-le avec Bash et GNU dd. Il accepte seulement une source fichier ordinaire et exige une nouvelle sortie. Il ne supprime pas un résultat partiel en cas d’échec, afin que vous puissiez l’inspecter.

#!/usr/bin/env bash
if [ "$#" -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then
  printf '%s\n' 'Usage : bash copier-dd.sh fichier-source nouveau-fichier' >&2
  exit 64
fi
source=$1
destination=$2
if [ ! -f "$source" ]; then
  printf '%s\n' 'La source doit être un fichier ordinaire.' >&2
  exit 66
fi
umask 077
dd if="$source" of="$destination" bs=1M conv=excl,fsync status=progress || {
  statut=$?
  printf '%s\n' 'La copie a échoué ; un fichier partiel peut rester.' >&2
  exit "$statut"
}
cmp -- "$source" "$destination" || {
  statut=$?
  printf '%s\n' 'La vérification de la copie a échoué.' >&2
  exit "$statut"
}
printf '%s\n' 'Copie et comparaison terminées.' 
bash copier-dd.sh "$espace/source.bin" "$espace/copie-verifiee.bin"

La réussite se termine par Copie et comparaison terminées. La source doit rester inchangée pendant la copie et la comparaison. cmp renvoie 0 si les octets coïncident, 1 s’ils diffèrent et un autre statut en cas de problème de lecture ou d’usage. Le script conserve le statut de l’opération qui échoue.

Le masque 077 limite les droits du nouveau fichier dans un environnement Unix ordinaire. Ce script n’est pas destiné à recevoir des chemins hostiles dans un service privilégié : -f et la copie sont des opérations séparées, et les composants des chemins peuvent changer entre elles. Le refus conv=excl est une protection de création de la sortie, pas une politique complète d’autorisation.

Préparer une image de périphérique et une restauration

Une image brute contient les octets du périphérique ou de la partition sélectionnée, y compris des zones qui ne sont pas des fichiers actifs. Identifiez d’abord le niveau voulu : une image de disque complet peut inclure la table de partitions et plusieurs partitions ; une image de partition ne représente pas automatiquement tout le disque.

lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,MOUNTPOINTS
findmnt

Vérifiez modèle, numéro de série, capacité, rôle du disque et tous les montages concernés, y compris les couches LVM, chiffrées ou RAID si elles existent. Un nom comme /dev/sdb peut changer après un redémarrage ; un identifiant persistant doit lui aussi être contrôlé au moment de l’opération. Les étapes de préparation des disques, partitions et montages aident à distinguer ces niveaux.

Pour une image cohérente, arrêtez les écritures selon les besoins du système et des applications, démontez la source lorsque c’est possible ou utilisez un mécanisme de snapshot coordonné approprié. Copier une base de données active sans coordination peut produire une image incohérente. Une destination d’image doit avoir assez d’espace et se trouver sur un stockage indépendant de la source.

Le modèle suivant lit un périphérique pour créer un nouveau fichier image. Les deux chemins de remplacement doivent être remplacés par des valeurs réellement vérifiées ; le chemin de sortie doit être un fichier neuf, pas un périphérique :

sudo dd if=/dev/disk/by-id/REMPLACER_SOURCE_VERIFIEE of=/CHEMIN_VERIFIE/nouvelle-image.img bs=4M status=progress conv=excl,fsync

La création via sudo peut donner une image appartenant à root : vérifiez les droits et restreignez l’accès, car elle peut contenir des données sensibles. Après une interruption ou une erreur, un fichier image peut rester incomplet. Conservez le statut final et le journal, puis comparez la quantité attendue et les données pertinentes sur une source restée stable.

Une restauration inverse la direction et écrase le périphérique de sortie. Le modèle ci-dessous concerne uniquement une image de disque complet dont le format a été confirmé et une cible remplaçable, non montée, au moins aussi grande en octets que l’image :

sudo dd if=/CHEMIN_VERIFIE/image-disque.img of=/dev/disk/by-id/REMPLACER_CIBLE_VERIFIEE bs=4M status=progress conv=fsync

Recontrôlez l’image, son empreinte de référence, le modèle et numéro de série de la cible, sa capacité exacte et l’absence d’utilisation avant cette écriture. Pour un disque système, travaillez depuis un environnement de secours adapté. Une écriture commencée ne se défait pas par une commande d’annulation ; le retour arrière dépend d’une sauvegarde indépendante.

Après la copie, contrôlez les structures et le contenu selon l’objectif. Comparer une image à un disque plus grand doit se limiter à la longueur pertinente de l’image ; le hachage du disque entier plus grand ne donnera pas nécessairement la même empreinte. Ne démarrez pas simultanément l’original et un clone sans examiner leurs identifiants et la configuration réseau.

Traiter les erreurs et choisir un autre outil si nécessaire

Le manuel GNU de dd décrit conv=noerror,sync : poursuivre après des erreurs de lecture et compléter les blocs. Les zéros ainsi ajoutés ne sont pas les données récupérées. Cette combinaison ne fournit pas à elle seule une carte persistante des zones récupérées et manquantes.

Pour un support qui présente des erreurs de lecture, GNU ddrescue et son mapfile permettent de privilégier les zones récupérables et de reprendre une récupération. Ne confondez pas ddrescue avec un simple changement d’options dd. Évitez de travailler sur une partition montée en lecture-écriture ou de réparer le système de fichiers original avant de préserver ce qui peut l’être.

Pour une sauvegarde répétée de fichiers vivants, un outil de copie ou de sauvegarde adapté aux attributs, à l’historique et à la cohérence applicative est généralement plus approprié qu’une image brute. Choisissez dd quand le flux d’octets et ses limites sont précisément ce que vous souhaitez copier, puis validez les données et la possibilité de restauration.