Modifiquei a resposta do xenoid para procurar especificamente por bytes nulos, com base em < a href="https://superuser.com/a/612336/764326"> a resposta desta outra pergunta sobre como grep para bytes nulos:
grep -Pal '\x00{512}' the_files
Eu recentemente recuperei parcialmente um disco defeituoso de 2,5 TB. ddrescue
criou uma imagem, que eu posso montar no modo de loopback, 2.1TB são recuperados, 450GB estão faltando, infelizmente espalhados por todo o disco.
Para ver quais arquivos são afetados, eu posso usar filefrag -v
e ver o arquivo de mapa gerado por ddrescue
.
MAS isso demoraria séculos. Descobri que, como são apenas arquivos de vídeo que estou recuperando, grandes extensões de zeros não são esperadas, mas estão presentes, onde ddrescue
não leu dados do disco.
Então eu precisaria de um comando para escanear um arquivo se houvesse um grande patch (arbitrário) de todos os zeros no arquivo. Na realidade, esses seriam sempre um múltiplo de 512 bytes e sempre começariam em um endereço de 512 bytes. Existe um comando que pode varrer um arquivo para uma seqüência de bytes binários (por exemplo, 512 × '\ 0')?
Modifiquei a resposta do xenoid para procurar especificamente por bytes nulos, com base em < a href="https://superuser.com/a/612336/764326"> a resposta desta outra pergunta sobre como grep para bytes nulos:
grep -Pal '\x00{512}' the_files
Fazer grep
parecer explicitamente para caracteres nulos me escapa. No entanto, fazer com que ele procure por 512 caracteres idênticos consecutivos (que são quase tão improváveis) é um pouco mais simples:
grep -Eal '(.){511}' the_files
lista os arquivos onde uma sequência de 512 caracteres idênticos foi encontrada. O parâmetro -a
é necessário para fazer com que ele corresponda a caracteres nulos (caso contrário, eles são considerados caracteres de fim de linha e ignorados).
a resposta do xenoid provavelmente encontrará arquivos afetados para você rapidamente. Para confirmar e analisar mais, você pode executar:
<"file" tr '<"file" tr '%pre%0-7' 'oL' | fold -w 512 | grep -vn 'L' | cut -f 1 -d ':'
0-7' 'oL' | fold -w 512 | grep -vn 'L' | cut -f 1 -d ':'
Funciona da seguinte forma:
"file"
é aberto e transmitido para o primeiro comando. tr
converte cada caractere nulo para o
, cada caractere não nulo para L
. fold
insere uma nova linha a cada 512 caracteres. Neste momento, o fluxo pode ser tratado como texto puro. grep
usa linhas que não contêm L
e as imprime com seus números. cut
isola esses números (expurgos ooo…
). Dessa forma, você obtém números ordinais de blocos de 512 bytes preenchidos com zeros. A numeração começa com 1
. Passe a saída para wc -l
para ver quantos fragmentos são afetados em um determinado arquivo.
Eu fiquei intrigado com isso, já que é algo que eu sempre quis, e eu pesquisei um pouco, encontrando este Python 3 programa .
Eu executei o comando wget
na parte inferior da página e ele funciona perfeitamente (embora você possa precisar de um sudo
, dependendo de suas permissões). Como grep
, ele possui muitas opções poderosas, incluindo pesquisas de Expressões Regulares: os exemplos no cabeçalho mostram alguns deles; bgrep --help
fornece a lista completa.
Para seu uso, você precisará de uma string de execução com 512 zeros duplos: não os digite, use algo como:
bgrep -l $(for f in {0..511}; do echo -n 00; done) files...
Você pode querer usar a opção -r
para percorrer uma árvore completa de diretórios.
Eu adicionei esta resposta, não porque os outros são inadequados (eu particularmente gostei da engenhosidade da sequência de comando de Kamil Maciorowski), mas porque pode ser de valor para outros (como eu) com problemas relacionados que se deparam com essa questão .
Diferente abordagem, portanto, outra resposta minha.
Você pode usar o ddrescue
para procurar zeros. Use --generate-mode
.
When
ddrescue
is invoked with the--generate-mode
option it operates in "generate mode", which is different from the default "rescue mode". That is, if you use the--generate-mode
option,ddrescue
does not rescue anything. It only tries to generate amapfile
for later use.[…]
ddrescue
can in some cases generate an approximatemapfile
, frominfile
and the (partial) copy inoutfile
, that is almost as good as an exactmapfile
. It makes this by simply assuming that sectors containing all zeros were not rescued.[…]
ddrescue --generate-mode infile outfile mapfile
( fonte )
Vamos fingir que seu arquivo é outfile
da execução anterior de ddrescue
. Não podemos usá-lo como infile
(porque ddrescue
se recusa a trabalhar quando infile
e outfile
são o mesmo arquivo), precisamos de um falso, /dev/zero
serve. Para encontrar todos os zero, você precisa de -b 1
. Este é o comando ( mapfile
não deve existir):
ddrescue -b 1 --generate-mode /dev/zero file mapfile
Toda entrada com ?
na lista de blocos de dados dentro de mapfile
significa um bloco de zeros (com -b 1
um zero também é um bloco). Consulte estrutura do arquivo de mapas para ddrescue
. Você pode então recuperar informações do mapfile
.
Por exemplo, o seguinte comando lhe dará o comprimento (hexadecimal, em bytes por causa de -b 1
) do maior bloco de zeros (saída vazia significa que não houve nenhum):
grep '0x.*0x.*[?]' mapfile | awk -F ' ' '{print $2}' | sort -ru | head -n 1
Para acelerar as coisas, você pode querer usar tamanho de bloco maior ( -b
), mas blocos de zeros que começam dentro de um bloco e terminam dentro do próximo podem passar despercebidos mesmo que sejam ligeiramente maiores que o tamanho de bloco escolhido ; seu deslocamento se torna importante.
Para não perder nenhum trecho de zeros de comprimento N
bytes ou mais, você precisa de um tamanho de bloco de no máximo M=$(((N+1)/2))
bytes (por exemplo, no máximo 5
para N=10
, 6
para N=11
). O comando
ddrescue -b "$M" --generate-mode /dev/zero file mapfile
gerará um arquivo de mapeamento onde cada linha com ?
na lista de blocos de dados significa pelo menos M
zeros (no deslocamento à direita), mas cada trecho de N
zeros (independentemente de seu deslocamento) gerará tal linha com certeza. Como dois blocos de M
são pelo menos N
, o seguinte raciocínio se aplica:
Colocar linhas com ?
da lista de blocos de dados,
mapfile
, lembre-se de que a unidade é M
) for 0x2
ou maior, você terá N
ou mais zeros nessa posição; 0x1
, você deverá investigar mais se houver pelo menos N
zeros ao redor dessa posição; N
zeros no arquivo com certeza. In reality, these would be always a multiple of 512 bytes, and always begin at a 512 byte address
Neste caso
ddrescue -b 512 --generate-mode /dev/zero file mapfile
irá encontrar e mapear todos eles.