Questão O que poderia fazer com que o comando file no Linux reportasse um arquivo de texto como dados?


Eu tenho um par de arquivos de origem C ++ (um .cpp e um .h) que estão sendo relatados como tipo dados pelo file comando no Linux. Quando eu corro o file -bi comando contra esses arquivos, recebo essa saída (mesma saída para cada arquivo):

application/octet-stream; charset=binary

Cada arquivo é claramente de texto simples (eu posso vê-los em vi). O que está causando file relatar incorretamente o tipo desses arquivos? Poderia ser algum tipo de coisa Unicode? Ambos os arquivos foram criados no Windows (usando o Visual Studio 2005), mas estão sendo compilados no Linux (é um aplicativo multi-plataforma).

Qualquer idéia seria apreciada.

Atualizar: Não vejo caracteres nulos em nenhum dos arquivos. Eu encontrei alguns caracteres estendidos no arquivo .cpp (em um bloco de comentário), removi-os, mas file ainda relata a mesma codificação. Eu tentei forçar a codificação no SlickEdit, mas isso não pareceu ter efeito. Quando abro o arquivo em vim, Eu vejo uma [converted] linha assim que eu abrir o arquivo. Talvez eu possa conseguir o vim para forçar a codificação?


4


origem


Algum caractere nulo neles? - Mehrdad
O que é uma maneira fácil de testar nulos no arquivo? Pelo que sei, eles não têm nenhum, mas isso não quer dizer que alguém tenha escapado para algum lugar ... - Jonah Bishop
Hmm ... você poderia abri-los em SciTE e verifique se há NUL caixa (ou procure por \0 com transformações de barra invertida). - Mehrdad
Tente "cat -v" para tornar os caracteres de controle visíveis. - Brian Swift
O que acontece quando você corre file -e soft filename? - Daniel Beck♦


Respostas:


Vim se esforça muito para entender o que quer que você jogue sem reclamar. Isso faz com que seja uma ferramenta relativamente pobre para diagnosticar filesaída.

O aviso "[convertido"] do Vim indica que havia algo no arquivo que o vim não esperaria ver na codificação de texto sugerida por suas configurações de local (LANG etc).

Outros já sugeriram

  • cat -v
  • xxd

Você pode tentar usar grepping para caracteres não-ASCII.

  • grep -P '[\x7f-\xff]' filename

A outra possibilidade é o fim de linha não padrão para a plataforma (ou seja, CRLF ou CR), mas eu esperaria file para lidar com isso e relatar "arquivo de texto do DOS" ou similar.


4



file não faz faça um bom trabalho de detectar arquivos de texto do DOS - iruvar
cat -v resolvi meu problema. obrigado. - RASG


Se você correr file -D filename, file exibe informações de depuração, incluindo os testes que realiza. Perto do final, ele mostrará qual teste foi bem-sucedido na determinação do tipo de arquivo.

Para um arquivo de texto normal, é assim:

[31> 0 regex,=^package[ \t]+[0-9A-Za-z_:]+ *;,""]
1 == 0 = 0
ascmagic 1
filename.txt: ISO-8859 text, with CRLF line terminators

Isto irá dizer-lhe o que encontrou para determinar que é esse tipo de mime.


3



Eu não vejo uma opção -D na minha instalação de arquivos (v5.04) ... - Jonah Bishop
Tente-d em vez disso. Isso funciona com o arquivo-5.03 como instalado no Fedora 11. - garyjohn
Notificando @JonahBishop sobre o comentário de garyjohn. Meu post foi escrito para o file incluído com o OS X. Meu Debian 6 não possui -d nem -D Apesar... - Daniel Beck♦
A bandeira -d funciona para mim, mas há tanta saída que não sei o que procurar ... - Jonah Bishop


Eu encontrei o problema usando a pesquisa binária para localizar as linhas problemáticas.

head -n {1/2 line count} file.cpp > a.txt
tail -n {1/2 line count} file.cpp > b.txt

Corrida file contra cada metade, e repetindo o processo, me ajudou a localizar a linha ofensiva. Eu encontrei um controle + P (^P) personagem incorporado nele. A remoção resolveu o problema. Escreverei um script Perl para procurar esses caracteres (e outros estendidos) no futuro.

Um grande obrigado a todos que forneceram uma resposta para todas as dicas!


3





isto poderia seja que os arquivos foram salvos com uma lista de materiais no começo deles, embora eu tenha pensado que uma versão recente do arquivo binário deveria reconhecer isso também.

Você já tentou jogá-los através de algo como "head -2 | xxd" e ver se há um BOM presente?

* BOM = Byte Order Mark - às vezes presente em arquivos de texto unicode. http://en.wikipedia.org/wiki/Byte_order_mark


0



Essa é uma dica interessante. Eu executei ambos os arquivos através do xxd e não vejo nenhum BOM na primeira posição de caractere. Cada arquivo começa com um bloco de comentário gigante, então eu vejo um monte de barras para começar. - Jonah Bishop
Cuidado para compartilhar um trecho? - GodEater
Isto é o que vejo do xxd dump: 0000000: 2f2f 2f2f 2f2f 2f2f 2f2f 2f2f 2f2f 2f2f //////////////// - Jonah Bishop


Provavelmente é um caractere não-ASCII do Unicode ou algum outro conjunto de caracteres. Desde que você esteja usando vi, que na maioria das distribuições Linux é alguma versão do vim, você pode procurar por esse caractere digitando

/[<Ctrl-V>x80-<Ctrl-V>xff]

e apertar Enter, onde <Ctrl-V> significa digitar v enquanto pressiona o Ctrl chave. Da mesma forma, você pode procurar por nulos (como Mehrdad sugeriu) com isso:

/<Ctrl-V>x00

0



Esta pesquisa resultou em um bloco de comentários contendo alguns caracteres estendidos no meu arquivo .cpp. No entanto, não vejo nenhum caractere similar no .h ... - Jonah Bishop
Eu atualizei minha resposta para incluir a busca por nulos, como Mehrdad sugeriu. - garyjohn
Não vejo caracteres nulos em nenhum dos arquivos. :( - Jonah Bishop


Que charset / encoding / (codepage) são os arquivos em?
Talvez os arquivos tenham caráter (s) perdido (s). normalmente de codificação cruzada incorreta entre diferentes plataformas. Dados inválidos em seus arquivos podem estar causando file para relatar como você descreveu. Você pode testar a validade de um arquivo para uma codificação charset específica testando-o com recode  (ou iconv).

Siga o link para uma lista de Codificações de caracteres comuns 

Este script lista as codificações de charset (de $my_csets) que não são válidos para o (s) seu (s) arquivo (s). Você pode listar todos os charsets via: recode -l 

file="$1"    
my_csets="UTF-16 UTF-8 windows-1250 ASCII"

# Use the next lines to test all charsets
# =======================================
# all_csets=$(recode -l |sed -ne "/^[^:/]/p" | awk '{print $1}')
# my_csets=$all_csets

for cset in $my_csets ;do 
  <"$1" recode $cset.. &>/dev/null || echo  "$cset  ERROR: $?"
done 

0