Quelles conditions doivent être remplies pour qu'un fichier soit un fichier texte tel que défini par POSIX?

22

POSIX définit un fichier texte comme:

Un fichier qui contient des caractères organisés en zéro ou plusieurs lignes. Les lignes ne contiennent pas de caractères NUL et aucune ne peut dépasser {LINE_MAX} octets de longueur, y compris le caractère <newline>. Bien que POSIX.1-2017 ne fasse pas de distinction entre les fichiers texte et les fichiers binaires (voir la norme ISO C), de nombreux utilitaires ne produisent une sortie prévisible ou significative que lorsqu'ils fonctionnent sur des fichiers texte. Les utilitaires standard qui ont de telles restrictions spécifient toujours des "fichiers texte" dans leurs sections STDIN ou INPUT FILES.

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

Cependant, il y a plusieurs choses que je trouve peu claires:

  1. Un fichier texte doit-il être un fichier normal? Dans l'extrait ci-dessus, il n'est pas dit explicitement que le fichier doit être un fichier normal

  2. Un fichier peut-il être considéré comme un fichier texte s'il contient un caractère et un seul caractère (c'est-à-dire un seul caractère qui ne se termine pas par une nouvelle ligne)? Je sais que cette question peut sembler compliquée, mais ils utilisent le mot "caractères" au lieu de "un ou plusieurs caractères". D'autres peuvent être en désaccord, mais s'ils signifient "un ou plusieurs caractères", je pense qu'ils devraient le dire explicitement

  3. Dans l'extrait ci-dessus, il fait référence aux "lignes". J'ai trouvé quatre définitions avec une ligne dans leur nom: "Ligne vide", "Ligne d'affichage", "Ligne incomplète" et "Ligne". Suis-je censé déduire qu'ils signifient "Ligne" en raison de leur omission de "Vide", "Affichage" et "Incomplet" - ou les quatre définitions incluses sont-elles toutes considérées comme une ligne dans l'extrait ci-dessus?

Toutes les questions qui viennent après ce bloc de texte dépendent de la déduction que "caractères" signifie "un ou plusieurs caractères":

  1. Puis-je inférer en toute sécurité que si un fichier est vide, il ne s'agit pas d'un fichier texte car il ne contient pas un ou plusieurs caractères?

Toutes les questions qui viennent après ce bloc de texte dépendent de la déduction que dans l'extrait ci-dessus, une ligne est définie comme une "ligne", et que les trois autres définitions contenant "ligne" dans leur nom doivent être exclues:

  1. Le «zéro» dans «zéro ou plusieurs lignes» signifie-t-il qu'un fichier peut toujours être considéré comme un fichier texte s'il contient un ou plusieurs caractères qui ne se terminent pas par un retour à la ligne?

  2. Est-ce que «zéro ou plusieurs lignes» signifie qu'une fois qu'une seule «ligne» (0 ou plusieurs caractères plus une nouvelle ligne de fin) entre en jeu, il devient illégal que la dernière ligne soit une «ligne incomplète» (une ou plusieurs non caractères de nouvelle ligne à la fin d'un fichier)?

  3. Est-ce que "aucune [aucune ligne] ne peut dépasser {LINE_MAX} octets de longueur, y compris le caractère de nouvelle ligne" signifie qu'il y a une limitation au nombre de caractères autorisés dans une "ligne" donnée dans un fichier texte (en passant, la valeur de LINE_MAX sur Ubuntu 18.04 et FreeBSD 11.1 est "2048")?

Harold Fischer
la source
Bonne question, Harold! Fait pour une grande discussion de terminologie. J'aimerais pouvoir voter plus longtemps
Sergiy Kolodyazhnyy

Réponses:

23
  1. Un fichier texte doit-il être un fichier normal? Dans l'extrait ci-dessus, il n'est pas dit explicitement que le fichier doit être un fichier normal

    Non; l'extrait note même spécifiquement l'entrée standard en tant que fichier texte potentiel. D'autres utilitaires standard, tels que make, utilisent spécifiquement le fichier spécial de caractères /dev/null comme fichier texte .

  2. Un fichier peut-il être considéré comme un fichier texte s'il contient un caractère et un seul caractère (c'est-à-dire un seul caractère qui ne se termine pas par une nouvelle ligne)?

    Ce caractère doit être un <newline>, ou ce n'est pas une ligne , et donc le fichier dans lequel il se trouve n'est pas un fichier texte. Un fichier contenant exactement l'octet 0A est un fichier texte sur une seule ligne. Une ligne vide est une ligne valide.

  3. Dans l'extrait ci-dessus, il fait référence aux "lignes". J'ai trouvé quatre définitions avec une ligne dans leur nom: "Ligne vide", "Ligne d'affichage", "Ligne incomplète" et "Ligne". Suis-je censé inférer qu'ils signifient "Ligne" en raison de leur omission de "Vide", "Affichage" et "Incomplet"

    Ce n'est pas vraiment une inférence, c'est juste ce qu'il dit. Le mot «ligne» a reçu une définition adaptée au contexte et c'est donc de cela qu'il parle.

  4. Puis-je inférer en toute sécurité que si un fichier est vide, il ne s'agit pas d'un fichier texte car il ne contient pas un ou plusieurs caractères?

    Un fichier vide se compose de zéro (ou plusieurs) lignes et est donc un fichier texte.

  5. Le «zéro» dans «zéro ou plusieurs lignes» signifie-t-il qu'un fichier peut toujours être considéré comme un fichier texte s'il contient un ou plusieurs caractères qui ne se terminent pas par un retour à la ligne?

    Non, ces personnages ne sont pas organisés en lignes.

  6. Est-ce que «zéro ou plusieurs lignes» signifie qu'une fois qu'une seule «ligne» (0 ou plusieurs caractères plus une nouvelle ligne de fin) entre en jeu, il devient illégal que la dernière ligne soit une «ligne incomplète» (une ou plusieurs non caractères de nouvelle ligne à la fin d'un fichier)?

    Ce n'est pas illégal , ce n'est tout simplement pas un fichier texte. Un utilitaire exigeant qu'un fichier texte lui soit donné peut se comporter de manière négative s'il est donné à la place.

  7. Est-ce que «aucune [aucune ligne] ne peut dépasser {LINE_MAX} octets de longueur, y compris le caractère de nouvelle ligne» signifie qu'il y a une limitation au nombre de caractères autorisés dans une «ligne» donnée dans un fichier texte

    Oui.

Cette définition essaie simplement de définir des limites sur ce qu'un utilitaire basé sur du texte ( par exemple,grep ) acceptera définitivement - rien de plus. Ils sont également libres d'accepter les choses plus libéralement, et le font souvent dans la pratique. Ils sont autorisés à utiliser un tampon de taille fixe pour traiter une ligne, à supposer qu'une nouvelle ligne apparaît avant qu'elle ne soit pleine, etc. Vous lisez peut-être trop de choses.

Michael Homer
la source
1
Êtes-vous sûr du point 2? La norme indique explicitement " 0 ou plusieurs lignes". Il en printf "a" > fileserait de même pour créer un fichier texte selon cette définition. Votre réponse à 4 semble contredire vos réponses à 2 et 5, car vous suggérez que touch filecrée un fichier texte alors que ce printf "a" > filen'est pas le cas.
terdon
4
@terdon: Je ne vois aucune contradiction dans la réponse de Michael. Fondamentalement, il semble dire qu'un fichier texte POSIX est un fichier dont le contenu correspond à l'expression rationnelle (.{0,M}\n)*(ancré implicitement et aux deux extrémités), où \ncorrespond à une nouvelle ligne et .correspond à tout caractère qui n'est pas une nouvelle ligne, et Mest un espace réservé pour la valeur numérique LINE_MAX-1. En particulier, cela implique qu'un fichier vide est un fichier texte valide composé de zéro ligne, mais que tout fichier texte non vide doit se terminer par une nouvelle ligne (car sinon il contiendrait une ligne incomplète et une ligne incomplète n'est pas une ligne ).
Ilmari Karonen
@Michael Homer Concernant le fichier classique, y a-t-il d'autres exemples en plus de / dev / null? Ce n'est pas vraiment un fichier texte car il contient un ou plusieurs caractères nuls.
Harold Fischer
1
@HaroldFischer /dev/nullest un fichier vide. Vous pensez /dev/zero.
Michael Homer
@HaroldFischer, non, se /dev/nulllit comme vide, car vous n'obtenez aucune donnée lorsque vous le lisez. Je ne suis pas sûr que cela ait beaucoup de sens de considérer les fichiers non réguliers ici, car beaucoup d'entre eux sont de nature dynamique. Cela inclut les tuyaux, les sockets, les périphériques char, qui sont essentiellement des interfaces de transport vers / depuis une autre entité. Ils ne contiennent aucun ensemble de données statiques, il serait donc plus logique de considérer les propriétés des données qui ont été transférées, au lieu des propriétés du fichier .
ilkkachu
7

Comme défini par POSIX:

Oui, un fichier texte est (essentiellement):

Un fichier qui contient des caractères organisés en zéro ou plusieurs lignes.

Il serait utile d'inclure également ces définitions:

3.92 Chaîne de caractères

Une séquence contiguë de caractères se terminant par et incluant le premier octet nul.

3.195 Ligne incomplète

Une séquence d'un ou plusieurs caractères non <nouvelle> à la fin du fichier.

3.206 Ligne

Une séquence de zéro ou plusieurs caractères non <nouvelle> plus un caractère <nouvelle> de fin.

3.243 Caractère de nouvelle ligne (<nouvelle>)

Un caractère qui dans le flux de sortie indique que l'impression doit commencer au début de la ligne suivante. C'est le caractère désigné par '\ n' dans le langage C. Il n'est pas spécifié si ce caractère est la séquence exacte transmise à un périphérique de sortie par le système pour effectuer le mouvement vers la ligne suivante.

3.247 NUL

Un caractère avec tous les bits mis à zéro.

Notez qu'un "fichier texte" ne doit pas contenir d'octets NUL.


Alors:

  1. Un fichier texte doit-il être un fichier normal?
    Non, ce n'est pas nécessaire. Un "fichier texte" est défini en termes de ce qu'il contient lors de la lecture. Si un fichier contient "zéro ou plusieurs lignes", c'est un fichier texte. Certains fichiers, comme /dev/stdin, peuvent contenir un fichier texte s'ils sont lus en même temps et non lors de la prochaine lecture.
  2. Un fichier peut-il être considéré comme un fichier texte s'il contient un caractère et un seul caractère…?
    Non, c'est une ligne incomplète (3.195).
    Un fichier texte ne doit contenir que des «lignes incomplètes».
  3. Suis-je censé en déduire qu'ils signifient «Line»…?
    Oui tu devrais.
  4. Puis-je inférer en toute sécurité que si un fichier est vide, ce n'est pas un fichier texte…?
    Non, un fichier vide (zéro caractère) est un "fichier texte" valide.
    D'en haut: … zéro ou plusieurs lignes… . Zéro ligne (zéro caractère) est un "fichier texte" valide.
  5. … Considéré comme un fichier texte s'il contient un ou plusieurs caractères qui ne se terminent pas par une nouvelle ligne?
    Non, une "ligne incomplète" n'est pas (techniquement) une "ligne" valide.
  6. Le «zéro» dans «zéro ou plusieurs lignes» signifie-t-il qu'un fichier peut toujours être considéré comme un fichier texte s'il contient un ou plusieurs caractères qui ne se terminent pas par un retour à la ligne?
    Non, une ligne incomplète n'est pas une "ligne". Un fichier texte ne doit pas comporter de lignes incomplètes.

  7. … Y a-t-il une limitation du nombre de caractères autorisés dans une «ligne» donnée dans un fichier texte…?
    Oui, pas plus de {LINE_MAX} octets (par opposition aux caractères) ne seront autorisés dans une ligne donnée d'un "fichier texte" valide.
    La valeur de {LINE_MAX} est donnée dans le fichier <limits.h>
    (lire aussi Sensible line buffer size in C? ):

    {LINE_MAX}
    Sauf indication contraire, la longueur maximale, en octets, de la ligne d'entrée d'un utilitaire (entrée standard ou autre fichier), lorsque l'utilitaire est décrit comme traitant des fichiers texte. La longueur comprend la place pour la queue.
    Valeur minimale acceptable: {_POSIX2_LINE_MAX}

    Pour un système basé sur GNU, il n'y a pas de limite définie (sauf la mémoire) :

    Macro: int LINE_MAX
    La plus grande ligne de texte prise en charge par les utilitaires POSIX.2 orientés texte. (Si vous utilisez les versions GNU de ces utilitaires, il n'y a pas de limite réelle, sauf celle imposée par la mémoire virtuelle disponible, mais la bibliothèque ne peut pas vous le dire.)

    Il semble être défini posix_lim.hpour être 2048 (au moins pour les systèmes GNU Linux 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
    

    Il peut également être trouvé à l'aide de l' utilitaire POSIX getconf :

    $ getconf LINE_MAX
    2048
    

Connexes: Pourquoi les fichiers texte devraient-ils se terminer par une nouvelle ligne?

Isaac
la source
2
Cette réponse est généralement correcte, mais la bonne réponse à «un fichier texte doit-il être un fichier normal» est non . Tout type de fichier peut être un fichier texte, c'est une question de contenu, le type de fichier n'est pas pertinent. L' fileutilitaire ne signale que le type de fichier pour les fichiers spéciaux, mais c'est exactement ainsi que l'utilitaire fonctionne, utilisez file - <…ou (Linux) file -s …pour voir son heuristique sur le contenu du fichier d'un fichier spécial. Un fichier spécial peut avoir un contenu différent chaque fois que vous l'ouvrez, il peut donc être ou être un fichier texte à chaque fois. /dev/nullest toujours un fichier texte car son contenu est toujours un fichier texte.
Gilles 'SO- arrête d'être méchant'
1
Plutôt que d'utiliser grepsur des fichiers, vous pouvez utiliser getconfpour obtenir des valeurs de configuration système, par exemple getconf LINE_MAX, qui, par ailleurs, renvoie 2048 (octets) sur mon système (Ubuntu 16.04).
heemayl
Je voulais trouver le fichier où la variable était définie, donc grep était nécessaire, et j'ai fait le travail (assez rapidement). Mais oui, getconfpermet de lire la valeur actuelle de config.
Isaac