Quais condições devem ser atendidas para que um arquivo seja um arquivo de texto conforme definido pelo POSIX?

22

POSIX define um arquivo de texto como:

Um arquivo que contém caracteres organizados em zero ou mais linhas. As linhas não contêm caracteres NUL e nenhuma pode exceder {LINE_MAX} bytes de comprimento, incluindo o caractere <newline>. Embora o POSIX.1-2017 não faça distinção entre arquivos de texto e arquivos binários (consulte o padrão ISO C), muitos utilitários produzem apenas resultados previsíveis ou significativos ao operar em arquivos de texto. Os utilitários padrão que possuem essas restrições sempre especificam "arquivos de texto" nas seções STDIN ou INPUT FILES.

Fonte: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403

No entanto, há várias coisas que acho incertas:

  1. Um arquivo de texto deve ser regular? No trecho acima, não diz explicitamente que o arquivo deve ser um arquivo regular

  2. Um arquivo pode ser considerado um arquivo de texto se contiver apenas um caractere e um caractere (ou seja, um único caractere que não termine com uma nova linha)? Sei que essa pergunta pode parecer insidiosa, mas eles usam a palavra "caracteres" em vez de "um ou mais caracteres". Outros podem discordar, mas se eles significam "um ou mais caracteres", acho que deveriam dizer isso explicitamente

  3. No trecho acima, ele faz referência a "linhas". Encontrei quatro definições com linhas no nome: "Linha Vazia", ​​"Linha de Exibição", "Linha Incompleta" e "Linha". Devo inferir que eles significam "Linha" devido à omissão de "Vazio", "Exibição" e "Incompleto" - ou todas essas quatro definições são inclusivas como consideradas uma linha no trecho acima?

Todas as perguntas que surgem após esse bloco de texto dependem da dedução de que "caracteres" significa "um ou mais caracteres":

  1. Posso deduzir com segurança que, se um arquivo está vazio, não é um arquivo de texto porque não contém um ou mais caracteres?

Todas as perguntas que surgem após esse bloco de texto dependem da dedução de que, no trecho acima, uma linha é definida como "Linha" e que as outras três definições que contêm "Linha" em seu nome devem ser excluídas:

  1. O "zero" em "zero ou mais linhas" significa que um arquivo ainda pode ser considerado um arquivo de texto se contiver um ou mais caracteres que não são finalizados com nova linha?

  2. "Zero ou mais linhas" significa que, uma vez que uma única "Linha" (0 ​​ou mais caracteres mais uma nova linha final) entra em jogo, torna-se ilegal que a última linha seja uma "Linha incompleta" (uma ou mais linhas não- caracteres de nova linha no final de um arquivo)?

  3. "Nenhuma [nenhuma linha] pode exceder {LINE_MAX} bytes de comprimento, incluindo o caractere de nova linha" significa que há uma limitação ao número de caracteres permitidos em qualquer "Linha" em um arquivo de texto (como um aparte, o valor de LINE_MAX no Ubuntu 18.04 e FreeBSD 11.1 é "2048")?

Harold Fischer
fonte
Boa pergunta, Harold! Faz uma grande discussão sobre terminologia. Gostaria de poder rever a pergunta mais vezes #
Sergiy Kolodyazhnyy 27/05

Respostas:

23
  1. Um arquivo de texto deve ser regular? No trecho acima, não diz explicitamente que o arquivo deve ser um arquivo regular

    Não; o trecho até observa especificamente a entrada padrão como um arquivo de texto em potencial. Outros utilitários padrão, como make, especificamente , usam o arquivo especial de caracteres /dev/null como um arquivo de texto .

  2. Um arquivo pode ser considerado um arquivo de texto se contiver apenas um caractere e um caractere (ou seja, um único caractere que não termine com uma nova linha)?

    Esse caractere deve ser um <newline>, ou isso não é uma linha e, portanto, o arquivo em que está não é um arquivo de texto. Um arquivo contendo exatamente o byte 0A é um arquivo de texto de linha única. Uma linha vazia é uma linha válida.

  3. No trecho acima, ele faz referência a "linhas". Encontrei quatro definições com linhas no nome: "Linha Vazia", ​​"Linha de Exibição", "Linha Incompleta" e "Linha". Devo inferir que eles significam "Linha" devido à omissão de "Vazio", "Exibição" e "Incompleto"

    Não é realmente uma inferência, é apenas o que diz. A palavra "linha" recebeu uma definição contextualmente apropriada e é sobre isso que está falando.

  4. Posso deduzir com segurança que, se um arquivo está vazio, não é um arquivo de texto porque não contém um ou mais caracteres?

    Um arquivo vazio consiste em zero (ou mais) linhas e, portanto, é um arquivo de texto.

  5. O "zero" em "zero ou mais linhas" significa que um arquivo ainda pode ser considerado um arquivo de texto se contiver um ou mais caracteres que não são finalizados com nova linha?

    Não, esses caracteres não estão organizados em linhas.

  6. "Zero ou mais linhas" significa que, uma vez que uma única "Linha" (0 ​​ou mais caracteres mais uma nova linha final) entra em jogo, torna-se ilegal que a última linha seja uma "Linha incompleta" (uma ou mais linhas não- caracteres de nova linha no final de um arquivo)?

    Não é ilegal , não é apenas um arquivo de texto. Um utilitário que exige que um arquivo de texto seja fornecido a ele pode se comportar adversamente se receber esse arquivo.

  7. "Nenhum [nenhuma linha] pode exceder {LINE_MAX} bytes de comprimento, incluindo o caractere de nova linha" significa que há uma limitação ao número de caracteres permitidos em qualquer "Linha" em um arquivo de texto

    Sim.

Essa definição está apenas tentando definir alguns limites sobre o que um utilitário baseado em texto ( por exemplogrep ) aceitará definitivamente - nada mais. Eles também são livres para aceitar as coisas de maneira mais liberal e, na maioria das vezes, na prática. Eles têm permissão para usar um buffer de tamanho fixo para processar uma linha, assumir que uma nova linha apareça antes de ficar cheia e assim por diante. Você pode estar lendo demais coisas.

Michael Homer
fonte
1
Você tem certeza do ponto 2? O padrão declara explicitamente " 0 ou mais linhas". Então printf "a" > file, criaria um arquivo de texto de acordo com essa definição. Sua resposta para 4 parece contradizer suas respostas para 2 e 5, pois você sugere que touch filecria um arquivo de texto enquanto printf "a" > fileisso não ocorre.
terdon
4
@terdon: Não vejo nenhuma contradição na resposta de Michael. Basicamente, ele parece estar dizendo que um arquivo de texto POSIX é qualquer arquivo cujo conteúdo corresponde à regexp (.{0,M}\n)*(implicitamente ancorada e nas duas extremidades), onde \ncorresponde a uma nova linha e a .qualquer caractere que não seja uma nova linha e Mé um espaço reservado para o valor numérico LINE_MAX-1. Em particular, isso implica que um arquivo vazio é um arquivo de texto válido que consiste em zero linhas, mas que qualquer arquivo de texto não vazio deve terminar em uma nova linha (pois, caso contrário, conteria uma linha incompleta e uma linha incompleta não é uma linha )
Ilmari Karonen
@ Michael Homer No que diz respeito ao arquivo regular, existem outros exemplos além de / dev / null? Na verdade, não é um arquivo de texto, pois contém um ou mais caracteres nulos.
Harold Fischer
1
@HaroldFischer /dev/nullé um arquivo vazio. Você está pensando /dev/zero.
Michael Homer
@HaroldFischer, não, /dev/nulllê como vazio, pois você não obtém dados quando os lê. Não sei se faz muito sentido considerar arquivos não regulares aqui, pois muitos deles são de natureza dinâmica. Isso inclui tubos, soquetes, dispositivos char, que são basicamente apenas interfaces de transporte para / de alguma outra entidade. Eles não contêm nenhum conjunto estático de dados, portanto, faria mais sentido considerar as propriedades dos dados que foram transferidos, em vez das propriedades do arquivo .
Ilkkachu
7

Conforme definido pelo POSIX:

Sim, um arquivo de texto é (basicamente):

Um arquivo que contém caracteres organizados em zero ou mais linhas.

Seria útil incluir também estas definições:

3.92 Sequência de caracteres

Uma sequência contígua de caracteres terminados por e incluindo o primeiro byte nulo.

3.195 Linha incompleta

Uma sequência de um ou mais caracteres não <newline> no final do arquivo.

3.206 Linha

Uma sequência de zero ou mais caracteres não <newline> mais um caractere <newline> final.

3.243 Caractere de nova linha (<nova linha>)

Um caractere que no fluxo de saída indica que a impressão deve começar no início da próxima linha. É o caractere designado por '\ n' no idioma C. Não é especificado se esse caractere é a sequência exata transmitida a um dispositivo de saída pelo sistema para realizar o movimento para a próxima linha.

3,247 NUL

Um caractere com todos os bits definidos como zero.

Observe que um "arquivo de texto" não deve conter NUL bytes.


Tão:

  1. Um arquivo de texto deve ser regular?
    Não, não precisa ser. Um "arquivo de texto" é definido em termos do que ele contém quando lido. Se um arquivo contiver "zero ou mais linhas", será um arquivo de texto. Alguns arquivos, como /dev/stdin, podem conter um arquivo de texto se forem lidos de uma só vez e não na próxima vez que forem lidos.
  2. Um arquivo pode ser considerado um arquivo de texto se contiver um caractere e apenas um caractere ...?
    Não, essa é uma linha incompleta (3.195).
    Um arquivo de texto deve conter apenas "Linhas incompletas".
  3. Devo inferir que eles significam "Linha" ...?
    Sim você deveria.
  4. Posso deduzir com segurança que, se um arquivo está vazio, não é um arquivo de texto ...?
    Não, um arquivo vazio (zero caracteres) é um "arquivo de texto" válido.
    De cima: … zero ou mais linhas… . Zero linhas (zero caracteres) é um "arquivo de texto" válido.
  5. ... considerado um arquivo de texto se ele contiver um ou mais caracteres que não sejam finalizados com nova linha?
    Não, uma "Linha incompleta" não é (tecnicamente) uma "linha" válida.
  6. O "zero" em "zero ou mais linhas" significa que um arquivo ainda pode ser considerado um arquivo de texto se contiver um ou mais caracteres que não são finalizados com nova linha?
    Não, uma linha incompleta não é uma "Linha". Um arquivo de texto não deve ter linhas incompletas.

  7. … Existe uma limitação ao número de caracteres permitido em qualquer "Linha" em um arquivo de texto ...?
    Sim, não é permitido mais do que {LINE_MAX} bytes (em oposição a caracteres) em qualquer linha de um "arquivo de texto" válido.
    O valor de {LINE_MAX} é fornecido no arquivo <limits.h>
    (leia também Tamanho sensível do buffer de linha em C? ):

    {LINE_MAX}
    Salvo indicação em contrário, o comprimento máximo, em bytes, da linha de entrada de um utilitário (entrada padrão ou outro arquivo), quando o utilitário é descrito como processando arquivos de texto. O comprimento inclui espaço para a trilha.
    Valor mínimo aceitável: {_POSIX2_LINE_MAX}

    Para um sistema baseado em GNU, não há limite definido (exceto memória) :

    Macro: int LINE_MAX
    A maior linha de texto que os utilitários POSIX.2 orientados a texto podem suportar. (Se você estiver usando as versões GNU desses utilitários, não haverá limite real, exceto o imposto pela memória virtual disponível, mas não há como a biblioteca lhe dizer isso.)

    Parece ser definido em posix_lim.h2048 (pelo menos para sistemas GNU Linux de 64 bits):

    $ grep -ri 'POSIX2_LINE_MAX' /usr/include/ 
    
    /usr/include/x86_64-linux-gnu/bits/xopen_lim.h:#define NL_LANGMAX       _POSIX2_LINE_MAX
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define _POSIX2_LINE_MAX                2048
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define LINE_MAX                _POSIX2_LINE_MAX
    

    Também pode ser encontrado usando o utilitário POSIX getconf :

    $ getconf LINE_MAX
    2048
    

Relacionado: Por que os arquivos de texto devem terminar com uma nova linha?

Isaac
fonte
2
Esta resposta está quase sempre correta, mas a resposta correta para "um arquivo de texto deve ser um arquivo normal" é não . Qualquer tipo de arquivo pode ser um arquivo de texto, é uma questão de conteúdo, o tipo de arquivo é irrelevante. O fileutilitário relata apenas o tipo de arquivo para arquivos especiais, mas é assim que o utilitário funciona, usa file - <…ou (Linux) file -s …para ver suas heurísticas no conteúdo do arquivo para um arquivo especial. Um arquivo especial pode ter conteúdos diferentes cada vez que você o abre, portanto pode ou ser um arquivo de texto a cada vez. /dev/nullé sempre um arquivo de texto porque seu conteúdo é sempre um arquivo de texto.
Gilles 'SO- stop be evil'
1
Em vez de usar grepem arquivos, você pode usar getconfpara obter valores de conf do sistema getconf LINE_MAX, por exemplo , que por sinal retornam 2048 (bytes) no meu sistema (Ubuntu 16.04).
Hemayl # 27/18
Eu queria encontrar o arquivo em que a variável foi definida, portanto, o grep era necessário e fiz o trabalho (muito rapidamente). Mas sim, getconfpermite ler o valor atual da configuração.
Isaac