¿Qué condiciones se deben cumplir para que un archivo sea un archivo de texto tal como lo define POSIX?

22

POSIX define un archivo de texto como:

Un archivo que contiene caracteres organizados en cero o más líneas. Las líneas no contienen caracteres NUL y ninguna puede superar los {LINE_MAX} bytes de longitud, incluido el carácter <newline>. Aunque POSIX.1-2017 no distingue entre archivos de texto y archivos binarios (consulte el estándar ISO C), muchas utilidades solo producen resultados predecibles o significativos cuando operan en archivos de texto. Las utilidades estándar que tienen tales restricciones siempre especifican "archivos de texto" en sus secciones STDIN o INPUT FILES.

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

Sin embargo, hay varias cosas que no entiendo:

  1. ¿Debe un archivo de texto ser un archivo normal? En el extracto anterior, no dice explícitamente que el archivo debe ser un archivo normal

  2. ¿Se puede considerar un archivo como un archivo de texto si contiene un carácter y solo un carácter (es decir, un solo carácter que no termina con una nueva línea)? Sé que esta pregunta puede sonar complicada, pero usan la palabra "caracteres" en lugar de "uno o más caracteres". Otros pueden estar en desacuerdo, pero si quieren decir "uno o más personajes" creo que deberían decirlo explícitamente

  3. En el extracto anterior, hace referencia a "líneas". Encontré cuatro definiciones con línea en su nombre: "Línea vacía", "Línea de visualización", "Línea incompleta" y "Línea". ¿Se supone que debo inferir que significan "Línea" debido a su omisión de "Vacío", "Pantalla" e "Incompleto", o son las cuatro definiciones incluidas como consideradas como una línea en el extracto anterior?

Todas las preguntas que aparecen después de este bloque de texto dependen de inferir que "caracteres" significa "uno o más caracteres":

  1. ¿Puedo inferir con seguridad que si un archivo está vacío, no es un archivo de texto porque no contiene uno o más caracteres?

Todas las preguntas que vienen después de este bloque de texto dependen de inferir que en el extracto anterior, una línea se define como una "Línea", y que las otras tres definiciones que contienen "Línea" en su nombre deben excluirse:

  1. ¿El "cero" en "cero o más líneas" significa que un archivo aún puede considerarse un archivo de texto si contiene uno o más caracteres que no terminan con nueva línea?

  2. ¿"Cero o más líneas" significa que una vez que entra en juego una sola "Línea" (0 ​​o más caracteres más una nueva línea de terminación), es ilegal que la última línea sea una "Línea Incompleta" (una o más líneas no caracteres de nueva línea al final de un archivo)?

  3. ¿"None [no line] puede exceder {LINE_MAX} bytes de longitud, incluido el carácter de nueva línea" significa que hay una limitación en el número de caracteres permitidos en cualquier "Línea" en un archivo de texto (como un aparte, el valor de LINE_MAX en Ubuntu 18.04 y FreeBSD 11.1 es "2048")?

Harold Fischer
fuente
Buena pregunta, Harold! Hace una gran discusión de la terminología. Ojalá pudiera votar la pregunta más veces
Sergiy Kolodyazhnyy

Respuestas:

23
  1. ¿Debe un archivo de texto ser un archivo normal? En el extracto anterior, no dice explícitamente que el archivo debe ser un archivo normal

    No; el extracto incluso señala específicamente la entrada estándar como un archivo de texto potencial. Otras utilidades estándar, como make, utilizan específicamente el archivo especial de caracteres /dev/null como archivo de texto .

  2. ¿Se puede considerar un archivo como un archivo de texto si contiene un carácter y solo un carácter (es decir, un solo carácter que no termina con una nueva línea)?

    Ese carácter debe ser una <línea nueva>, o esto no es una línea , por lo que el archivo en el que se encuentra no es un archivo de texto. Un archivo que contiene exactamente el byte 0A es un archivo de texto de una sola línea. Una línea vacía es una línea válida.

  3. En el extracto anterior, hace referencia a "líneas". Encontré cuatro definiciones con línea en su nombre: "Línea vacía", "Línea de visualización", "Línea incompleta" y "Línea". ¿Se supone que debo inferir que significan "Línea" debido a su omisión de "Vacío", "Pantalla" e "Incompleto"

    No es realmente una inferencia, es solo lo que dice. A la palabra "línea" se le ha dado una definición contextualmente apropiada y de eso se trata.

  4. ¿Puedo inferir con seguridad que si un archivo está vacío, no es un archivo de texto porque no contiene uno o más caracteres?

    Un archivo vacío consta de cero (o más) líneas y, por lo tanto, es un archivo de texto.

  5. ¿El "cero" en "cero o más líneas" significa que un archivo aún puede considerarse un archivo de texto si contiene uno o más caracteres que no terminan con nueva línea?

    No, estos personajes no están organizados en líneas.

  6. ¿"Cero o más líneas" significa que una vez que entra en juego una sola "Línea" (0 ​​o más caracteres más una nueva línea de terminación), es ilegal que la última línea sea una "Línea Incompleta" (una o más líneas no caracteres de nueva línea al final de un archivo)?

    No es ilegal , simplemente no es un archivo de texto. Una utilidad que requiere que se le dé un archivo de texto puede comportarse negativamente si se le da ese archivo.

  7. ¿"None [no line] puede exceder {LINE_MAX} bytes de longitud, incluido el carácter de nueva línea" significa que hay una limitación en el número de caracteres permitidos en cualquier "Línea" en un archivo de texto

    Sí.

Esta definición solo está tratando de establecer algunos límites sobre lo que una utilidad basada en texto ( por ejemplogrep ) definitivamente aceptará, nada más. También son libres de aceptar las cosas de manera más liberal, y muy a menudo lo hacen en la práctica. Se les permite usar un búfer de tamaño fijo para procesar una línea, asumir que aparece una nueva línea antes de que esté llena, y así sucesivamente. Puede que estés leyendo demasiado sobre las cosas.

Michael Homer
fuente
1
¿Estás seguro del punto 2? El estándar establece explícitamente " 0 o más líneas". Entonces printf "a" > filecrearía un archivo de texto de acuerdo con esa definición. Su respuesta a 4 parece estar contradiciendo sus respuestas a 2 y 5, ya que sugiere que touch filecrea un archivo de texto mientras printf "a" > fileque no.
terdon
44
@terdon: No veo ninguna contradicción en la respuesta de Michael. Básicamente, parece estar diciendo que un archivo de texto POSIX es cualquier archivo cuyo contenido coincide con la expresión regular (.{0,M}\n)*(implícitamente anclado y ambos extremos), donde \ncoincide con una nueva línea y .coincide con cualquier carácter que no sea una nueva línea, y Mes un marcador de posición para el valor numérico LINE_MAX-1. En particular, esto implica que un archivo vacío es un archivo de texto válido que consta de cero líneas, pero que cualquier archivo de texto no vacío debe terminar en una nueva línea (ya que de lo contrario contendría una línea incompleta y una línea incompleta no es una línea )
Ilmari Karonen
@Michael Homer Con respecto al archivo regular, ¿hay otros ejemplos además de / dev / null? No es realmente un archivo de texto ya que contiene uno o más caracteres nulos.
Harold Fischer
1
@HaroldFischer /dev/nulles un archivo vacío. Usted está pensando /dev/zero.
Michael Homer
@HaroldFischer, no, se /dev/nulllee como vacío, ya que no obtienes datos cuando lo lees. No estoy seguro de que tenga mucho sentido considerar archivos no regulares aquí, ya que muchos de ellos son de naturaleza dinámica. Eso incluye tuberías, enchufes, dispositivos char, que son básicamente interfaces de transporte hacia / desde alguna otra entidad. No contienen ningún conjunto estático de datos, por lo que tendría más sentido considerar las propiedades de los datos que se transfirieron, en lugar de las propiedades del archivo .
ilkkachu
7

Según lo definido por POSIX:

Sí, un archivo de texto es (básicamente):

Un archivo que contiene caracteres organizados en cero o más líneas.

Sería útil incluir también estas definiciones:

3.92 Cadena de caracteres

Una secuencia contigua de caracteres terminados por e incluyendo el primer byte nulo.

3.195 Línea incompleta

Una secuencia de uno o más caracteres que no son <línea nueva> al final del archivo.

Línea 3.206

Una secuencia de cero o más caracteres que no son <newline> más un carácter <newline> que termina.

3.243 Carácter de nueva línea (<nueva línea>)

Un carácter que en la secuencia de salida indica que la impresión debe comenzar al comienzo de la siguiente línea. Es el carácter designado por '\ n' en el lenguaje C. No se especifica si este carácter es la secuencia exacta transmitida a un dispositivo de salida por el sistema para lograr el movimiento a la siguiente línea.

3.247 NUL

Un personaje con todos los bits puestos a cero.

Tenga en cuenta que un "archivo de texto" no contendrá bytes NUL.


Asi que:

  1. ¿Debe un archivo de texto ser un archivo normal?
    No, no tiene por qué serlo. Un "archivo de texto" se define en términos de lo que contiene cuando se lee. Si un archivo contiene "cero o más líneas", es un archivo de texto. Algunos archivos, como /dev/stdin, pueden contener un archivo de texto si se leen al mismo tiempo y no la próxima vez que se lean.
  2. ¿Se puede considerar un archivo como un archivo de texto si contiene un carácter y un solo carácter ...?
    No, esa es una línea incompleta (3.195).
    Un archivo de texto solo debe tener no "Líneas incompletas".
  3. ¿Se supone que debo inferir que significan "Línea" ...?
    Si deberías.
  4. ¿Puedo inferir con seguridad que si un archivo está vacío, no es un archivo de texto ...?
    No, un archivo vacío (cero caracteres) es un "archivo de texto" válido.
    Desde arriba: ... cero o más líneas ... . Cero líneas (cero caracteres) es un "archivo de texto" válido.
  5. ... ¿consideró un archivo de texto si contiene uno o más caracteres que no terminan con nueva línea?
    No, una "Línea incompleta" no es (técnicamente) una "línea" válida.
  6. ¿El "cero" en "cero o más líneas" significa que un archivo aún puede considerarse un archivo de texto si contiene uno o más caracteres que no terminan con nueva línea?
    No, una línea incompleta no es una "Línea". Un archivo de texto no debe tener líneas incompletas.

  7. ... hay una limitación en el número de caracteres permitidos en cualquier "Línea" en un archivo de texto ...?
    Sí, no se permitirán más de {LINE_MAX} bytes (a diferencia de los caracteres) en cualquier línea de un "archivo de texto" válido.
    El valor de {LINE_MAX} se proporciona en el archivo <limits.h>
    (también se lee ¿ Tamaño de búfer de línea sensible en C? ):

    {LINE_MAX}
    A menos que se indique lo contrario, la longitud máxima, en bytes, de la línea de entrada de una utilidad (entrada estándar u otro archivo), cuando la utilidad se describe como procesamiento de archivos de texto. La longitud incluye espacio para el seguimiento.
    Valor mínimo aceptable: {_POSIX2_LINE_MAX}

    Para un sistema basado en GNU no hay un límite establecido (excepto la memoria) :

    Macro: int LINE_MAX
    La línea de texto más grande que las utilidades POSIX.2 orientadas a texto pueden admitir. (Si está utilizando las versiones GNU de estas utilidades, entonces no hay límite real, excepto el impuesto por la memoria virtual disponible, pero no hay forma de que la biblioteca pueda decirle esto).

    Parece estar definido en posix_lim.h2048 (al menos para sistemas Linux GNU 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
    

    También se puede encontrar utilizando la utilidad POSIX getconf :

    $ getconf LINE_MAX
    2048
    

Relacionado: ¿Por qué los archivos de texto deben terminar con una nueva línea?

Isaac
fuente
2
Esta respuesta es mayormente correcta, pero la respuesta correcta a "debe un archivo de texto ser un archivo normal" es no . Cualquier tipo de archivo puede ser un archivo de texto, es una cuestión de contenido, el tipo de archivo es irrelevante. La fileutilidad solo informa el tipo de archivo para archivos especiales, pero así es como funciona la utilidad, use file - <…o (Linux) file -s …para ver su heurística en el contenido del archivo para un archivo especial. Un archivo especial puede tener diferentes contenidos cada vez que lo abra, por lo que puede ser un archivo de texto cada vez. /dev/nullsiempre es un archivo de texto porque su contenido es siempre un archivo de texto.
Gilles 'SO- deja de ser malvado'
1
En lugar de usar grepen archivos, puede usar getconfpara obtener valores de configuración del sistema getconf LINE_MAX, por ejemplo , que por cierto devuelve 2048 (bytes) en mi sistema (Ubuntu 16.04).
heemayl
Quería encontrar el archivo donde se definió la variable, por lo tanto, grep era necesario, e hice el trabajo (bastante rápido). Pero sí, getconfpermite leer el valor actual de config.
Isaac