Qual é o comando da linha de comando do Linux que pode identificar esses arquivos?
AFAIK o find
comando (ou grep
) só pode corresponder a uma sequência específica dentro do arquivo de texto. Mas quero combinar o conteúdo inteiro, ou seja, quero ver quais arquivos correspondem à expressão regular \0+
, ignorando o (s) caractere (s) de final de linha . Talvez o find . cat | grep
idioma possa funcionar, mas não sei como fazer grep ignorar linhas (e tratar o arquivo como binário).
Antecedentes: todos os dias, quando meu laptop congela, minha partição btrfs perde informações: os arquivos abertos para gravação recebem seu conteúdo substituído por zeros (o tamanho do arquivo permanece mais ou menos intacto). Uso a sincronização e não quero que esses arquivos falsos se propaguem: preciso de uma maneira de identificá-los para que possa obtê-los do backup.
fonte
-v
opção de grep: filtrar todos os ficheiros que tenham qualquer byte 1 a 255.Respostas:
Você pode
grep
obter using caracteres usando o modo regex Perl:Então você pode usar isso:
fonte
GNU grep 2.5.4
. Independentemente de eu usar--binary-files=text
ou--binary-files=binary
, ele fornece umtrue
resultado para todos os valores de dados não vazios, por exemplo."\0\0"
,"\0x\0"
,"abcd"
... O código exato que usei é:for typ in binary text ;do for dat in '\0\0' '\0x\0' 'abcd' '' ;do printf "$dat" >f; grep --binary-files=$typ -P '[^\0]' f >/dev/null && echo true || echo false; done; done
GNU grep) 2.10
. Esta versão mais recente fornece os resultados esperados ... então, um +1 tardioprintf '\0\n\0\0\n\n' > file
ouprintf '\n' > file
para esse assunto.\0
e\n
caracteres (mesmo zero de qualquer um) seria uma correspondência.Eu concordo com o que D_Bye diz sobre encontrar a raiz do problema.
De qualquer forma, verifique se um arquivo contém apenas
\0
e / ou\n
você pode usartr
:Que retorna 0 para arquivos nulos / nova linha e vazios.
fonte
tr -d '\0\n'
resolve o problema da nova linha, que deixa apenas o problema (?) dos arquivos vazios listados na saída ... No entanto, ele processa todos os bytes de cada arquivo (o que pode ou não ser um problema) +1Eu suspeito que esses arquivos sejam escassos, ou seja, eles não têm espaço em disco alocado para eles, eles apenas especificam o tamanho do arquivo (
du
informaria 0 para eles).Nesse caso, com o GNU find, você pode fazer (assumindo que nenhum caminho do arquivo contenha caracteres de nova linha):
fonte
du
evitará riscar o conteúdo de cada arquivo no sistema de arquivos, portanto, todo o procedimento não levará mais de 30 minutos para ser concluído.printf %b
acima relatórios quedu
iria relatar)-size +0
para-size +1
arquivos de tamanho zero são excluídos dos resultados. Também os arquivos que contêm\n
seu caminho causarão problemas para este comando.-size +0
é para tamanhos estritamente maiores que 0.-size +1
seria para tamanhos estritamente maiores que 512. A limitação da nova linha já foi mencionada.-size +1
, você está realmente correto. Eu consertei minha resposta. :-)Aqui está um pequeno programa python que pode fazer isso:
E em ação:
Você pode verificar vários arquivos usando descoberta de
-exec
,xargs
, GNUparallel
, e programas semelhantes. Como alternativa, isso imprimirá nomes de arquivos que precisam ser tratados:Lembre-se de que se você passar a saída disso para outro programa, os nomes de arquivos podem conter novas linhas, portanto, você deve delimitá-lo de maneira diferente (apropriadamente, com
\0
).Se você tiver muitos arquivos, seria melhor usar uma opção para processamento paralelo, pois isso lê apenas um arquivo por vez.
fonte
/etc/nologin
,~/.hushlogin
,.nomedia
, ...) são erroneamente identificada por esta resposta.Encontre arquivos que contenham apenas caracteres nulos '\ 0' e caracteres de nova linha '\ n'.
O
q
in sed faz com que cada pesquisa de arquivo seja encerrada imediatamente após encontrar qualquer caractere não nulo em uma linha.Faça arquivos de teste
resultado
fonte
-print0
argumento parece estar faltandofind
ou aIFS=
parte está confusa. Qual era o delimitador pretendido?Este one-liner é a forma mais eficiente de encontrar 100% arquivos nul usando GNU
find
,xargs
egrep
(assumindo que o último é construído com o apoio PCRE):As vantagens deste método sobre outras respostas fornecidas são:
Permission denied
avisos.grep
interromperá a leitura dos dados dos arquivos após localizar qualquer byte diferente de nulo (LC_ALL=C
é usado para garantir que cada byte seja interpretado como um caractere ).grep
processos verificam com eficiência vários arquivos.-
são tratados corretamente.Passar a
-Z
opção paragrep
e usarxargs -r0 ...
permite que outras ações sejam executadas nos arquivos 100% nul (por exemplo: limpeza):Eu também recomendo usar as
find
opções-P
para evitar seguir links simbólicos e-xdev
evitar percorrer sistemas de arquivos (por exemplo: montagens remotas, árvores de dispositivos, montagens de ligação, etc).Para ignorar o (s) caractere (s) de final de linha , a seguinte variante deve funcionar (embora eu não ache que seja uma boa ideia):
Juntando tudo, incluindo a remoção de arquivos indesejados (100% de caracteres nul / nova linha) para impedir o backup:
Eu não recomendo incluir arquivos vazios (zero bytes), eles geralmente existem para fins muito específicos .
fonte
\0
buraco de 900 MB) e momento atual dos resultados. Se você fizer isso de uma maneira que a referência seja convincente para você, provavelmente será convincente para todos nós-P
é o padrão emfind
. Se você deseja seguir os links simbólicos, é-L
/-follow
. Você verá que o POSIX nem mesmo especifica essa opçãofind
(mesmo que o POSIX tenha introduzido -P / -H / -L para alguns comandos).Para usar o GNU sed, você pode usar a
-z
opção, que define uma linha como seqüências terminadas em zero e corresponde e exclui linhas vazias da seguinte forma:O comando head inbetween é apenas uma otimização.
fonte
Pitão
Único arquivo
Defina o alias:
Teste-o:
Vários arquivos
Encontre todos os arquivos binários recursivamente:
Para encontrar todos os arquivos não binários, altere
&&
com||
.fonte