moyen rapide de trouver de grandes étendues de zéros dans des fichiers

4

J'ai récemment partiellement récupéré un disque défectueux de 2,5 To. ddrescuecréé une image, que je peux monter en mode boucle, 2.1To sont récupérés, 450 Go sont manquants, malheureusement répartis sur tout le disque.

Pour voir quels fichiers sont affectés, je pourrais utiliser filefrag -vet consulter le fichier de carte généré par ddrescue.

MAIS cela prendrait des siècles. J'ai découvert que, comme ce ne sont que des fichiers vidéo que je récupère, il ne faut pas s'attendre à de grandes zones de zéros, mais ils sont présents et ddrescuene lisent pas les données du disque.

Il me faudrait donc une commande pour analyser un fichier s'il y a un gros patch (arbitraire) de tous les zéros dans le fichier. En réalité, ils sont toujours un multiple de 512 octets et commencent toujours à une adresse de 512 octets. Existe-t-il une commande permettant d’analyser dans un fichier une telle séquence d’octets binaires (512 × '\ 0')?

Ro-ee
la source
Le fichier journal produit par ddrescuecontiendra exactement quelles zones n'ont pas été clonées. Vous pouvez également utiliser ddrescueview pour les voir.
Andrea Lazzarotto
oui, mais je dois utiliser filefrag pour trouver quels blocs sont utilisés par un certain fichier. Une recherche inversée du fichier de carte à imprimer pour chaque * ou? ou - la zone marquée dans le fichier de la carte, quel fichier elle affectait ferait évidemment l'affaire: je verrais tous les fichiers affectés et supposerais que les fichiers non mentionnés sont corrects. Mais je m'en tiendrai à la réponse donnée par xenoid, sa vitesse est convenable.
Ro-ee

Réponses:

4

J'ai modifié la réponse de xenoid pour rechercher spécifiquement les octets nuls, sur la base de la réponse de cette autre question sur la façon de rechercher des octets nuls dans grep:

grep -Pal '\x00{512}' the_files
MJ713
la source
J'ai effectué des analyses comparatives à ce sujet. Avec cette version installée sur mon système, il faut 20 secondes au lieu de 2 minutes pour que le même fichier passe par grep ... naturellement, car rechercher une séquence spécifique est bien plus rapide que de rechercher TOUTE séquence égale. personnages de même longueur ...
Ro-ee
2

Rechercher grepexplicitement des caractères nuls m'échappe. Cependant, faire apparaître 512 caractères identiques consécutifs (ce qui est presque aussi improbable) est un peu plus simple:

grep -Eal '(.)\1{511}' the_files

répertorie les fichiers contenant une séquence de 512 caractères identiques. Le -aparamètre est nécessaire pour faire correspondre les caractères nuls (sinon, ils sont considérés comme des caractères de fin de ligne et sont ignorés).

xénoïde
la source
2

La réponse de xenoid trouvera probablement les fichiers concernés pour vous rapidement. Pour confirmer et analyser davantage, vous pouvez exécuter:

<"file" tr '\000-\377' 'oL' | fold -w 512 | grep -vn 'L' | cut -f 1 -d ':'

Cela fonctionne comme suit:

  1. "file" est ouvert et diffusé à la première commande.
  2. trconvertit chaque caractère null en o, chaque caractère non-null en L.
  3. foldinsère une nouvelle ligne après 512 caractères. À ce moment, le flux peut être traité comme du texte pur.
  4. grepprend les lignes qui ne contiennent pas Let les imprime avec leurs numéros.
  5. cutisole ces nombres (purges ooo…).

De cette façon, vous obtenez des nombres ordinaux de morceaux de 512 octets remplis de zéros. La numérotation commence par 1. Passez la sortie à wc -lpour voir combien de morceaux sont affectés dans un fichier donné.

Kamil Maciorowski
la source
C'est de la magie avancée ... J'ai écrit un petit programme qui essaie de récupérer les blocs manquants des disques d'origine et qui effectue déjà les calculs corrects, mais qui est assez lent, mais avec ce programme, je peux savoir combien de Mo manquent . Je vais essayer votre solution, car je suppose que cela pourrait être plus rapide.
Ro-ee
2

Approche différente, donc une autre réponse de ma part.

Vous pouvez vous utiliser ddrescuepour rechercher des zéros. Utilisez --generate-mode.

Quand ddrescueest appelé avec l' --generate-modeoption, il fonctionne en "mode de génération", ce qui diffère du "mode de secours" par défaut. C'est-à-dire que si vous utilisez l' --generate-modeoption, ddrescuerien ne sera sauvé. Il essaie seulement de générer un mapfilepour une utilisation ultérieure.

[…]

ddrescuepeut dans certains cas générer une copie approximative mapfile, à partir de infileet la copie (partielle) outfile, qui est presque aussi bonne qu’une copie exacte mapfile. Cela se fait simplement en supposant que les secteurs contenant tous les zéros n’ont pas été sauvés.

[…]

ddrescue --generate-mode infile outfile mapfile

( source )

Supposons que votre fichier provient outfiled'une ddrescueexécution précédente . Nous ne pouvons pas l'utiliser comme infile(parce que ddrescuerefuse de travailler quand infileet outfilesont le même fichier), nous avons besoin d'un fichier factice, /dev/zerofera l'affaire. Pour trouver chaque zéro dont vous avez besoin -b 1. C'est la commande ( mapfilene doit pas exister):

ddrescue -b 1 --generate-mode /dev/zero file mapfile

Chaque entrée avec ?dans la liste des blocs de données à l'intérieur du mapfilebloc signifie un bloc de zéros ( -b 1un seul zéro est aussi un bloc). Voir la structure du mapfile pourddrescue . Vous pouvez ensuite récupérer des informations à partir du fichier mapfile.

Par exemple, la commande suivante vous donnera la longueur (hexadécimale, en octets à cause de -b 1) du plus grand bloc de zéros (une sortie vide signifie qu'il n'y en avait pas):

grep '0x.*0x.*[?]' mapfile | awk -F ' ' '{print $2}' | sort -ru | head -n 1

Pour accélérer les choses, vous pouvez utiliser une taille de bloc plus grande ( -b), mais les blocs de zéros commençant par un bloc et se terminant par le suivant peuvent ne pas être remarqués, même s’ils sont légèrement plus longs que la taille de bloc choisie; leur décalage devient important.

Pour ne rater aucune portion de zéros d’ Noctets de longueur ou plus, vous devez disposer d’une taille de bloc d'au plus M=$(((N+1)/2))octets (par exemple, au plus 5pour N=10, 6pour N=11). La commande

ddrescue -b "$M" --generate-mode /dev/zero file mapfile

générera un mapfile où chaque ligne ?dans la liste des blocs de données signifie au moins Mzéro (décalage correct), mais chaque portion de Nzéros (quel que soit son décalage) générera une telle ligne à coup sûr. Puisque deux blocs de Msont au moins N, le raisonnement suivant s'applique:

Prendre des lignes avec ?de la liste des blocs de données,

  • Si la longueur (deuxième colonne de la mapfile, rappelez-vous que l'unité est M) est 0x2supérieure Nou égale à 0, vous avez ou plusieurs zéros à cette position;
  • si la longueur est 0x1alors vous devriez enquêter davantage s'il y a au moins des Nzéros autour de cette position;
  • s'il n'y a pas de telle ligne, il n'y a pas de Nzéros dans le fichier à coup sûr.

En réalité, ils seraient toujours un multiple de 512 octets et commenceraient toujours à une adresse de 512 octets.

Dans ce cas

ddrescue -b 512 --generate-mode /dev/zero file mapfile

va trouver et cartographier tous.

Kamil Maciorowski
la source
C’est la méthode que j’ai utilisée ici, puis ddrescueview pour obtenir une présentation graphique plus pratique: superuser.com/questions/1267818/…
GabrielB
1

Cela m’intriguait, car c’était quelque chose que j’avais parfois voulu, et j’ai fait quelques recherches pour proposer ce programme Python 3 .

J'ai exécuté la wgetcommande au bas de la page et cela fonctionne parfaitement (vous aurez peut-être besoin d'une sudo, en fonction de vos autorisations). Par exemple grep, il offre de nombreuses options puissantes, y compris des recherches d’expression régulière: les exemples dans l’en-tête en montrent quelques-unes; bgrep --helpdonne la liste complète.

Pour votre utilisation, vous aurez besoin d'une chaîne d'exécution contenant 512 doubles zéros: ne les tapez pas, utilisez quelque chose comme:

bgrep -l $(for f in {0..511}; do echo -n 00; done) files...

Vous pouvez utiliser cette -roption pour parcourir une arborescence de répertoires complète.

J'ai ajouté cette réponse, non pas parce que les autres sont inadéquats (j'ai particulièrement aimé l'ingéniosité de la séquence de commandes de Kamil Maciorowski), mais parce qu'elle peut être utile aux autres (comme moi) aux problèmes connexes qui rencontrent cette question.

AFH
la source