web-dev-qa-db-fra.com

Pas de nouvelle ligne en fin de fichier

Lorsque vous faites un git diff il est dit "Pas de nouvelle ligne à la fin du fichier".

Ok, il n'y a pas de nouvelle ligne à la fin du fichier. Quel est le problème?

Quelle est la signification du message et que tente-t-il de nous dire?

410
Pacerier

Cela indique que vous n'avez pas de nouvelle ligne (généralement '\n', également appelée CR ou CRLF) à la fin du fichier.

Autrement dit, le dernier octet (ou les octets si vous utilisez Windows) du fichier n’est pas une nouvelle ligne.

Le message est affiché car sinon, il n'y a aucun moyen de faire la différence entre un fichier où il y a une nouvelle ligne à la fin et un autre où il ne l'est pas. De toute façon, Diff doit sortir une nouvelle ligne, sans quoi le résultat serait plus difficile à lire ou à traiter automatiquement.

Notez que c'est un bon style de toujours mettre la nouvelle ligne en dernier caractère si le format de fichier le permet. De plus, par exemple, pour les fichiers d'en-tête C et C++, il est requis par le standard de langage.

407
Alexander Gladysh

Ce n'est pas seulement un mauvais style, cela peut conduire à un comportement inattendu lors de l'utilisation d'autres outils sur le fichier.

Voici test.txt:

first line
second line

Il n'y a pas de caractère de nouvelle ligne sur la dernière ligne. Voyons combien de lignes sont dans le fichier:

$ wc -l test.txt
1 test.txt

Peut-être que c'est ce que vous voulez, mais dans la plupart des cas, vous vous attendriez probablement à ce qu'il y ait 2 lignes dans le fichier.

De plus, si vous souhaitez combiner des fichiers, il se peut que votre comportement ne soit pas celui attendu:

$ cat test.txt test.txt
first line
second linefirst line
second line

Enfin, les diffs seraient un peu plus bruyants si vous deviez ajouter une nouvelle ligne. Si vous avez ajouté une troisième ligne, cela afficherait une modification sur la deuxième ligne ainsi que le nouvel ajout.

86
Dean

La seule raison est qu'Unix avait historiquement une convention de tous les fichiers texte lisibles par l'homme se terminant par une nouvelle ligne. À l'époque, cela évitait un traitement supplémentaire lors de l'affichage ou de la jonction de fichiers texte et évitait de traiter les fichiers texte différemment des fichiers contenant d'autres types de données (par exemple, des données binaires brutes non lisibles par l'homme).

En raison de cette convention, de nombreux outils de cette époque attendent la fin de ligne, notamment les éditeurs de texte, les outils de différenciation et d'autres outils de traitement de texte. Mac OS X a été construit sur BSD Unix et Linux a été développé pour être compatible Unix. Les deux systèmes d'exploitation ont donc hérité de la même convention, du même comportement et des mêmes outils.

Windows n'a pas été développé pour être compatible Unix, il n'a donc pas la même convention et la plupart des logiciels Windows se débrouilleront sans problème de fin de ligne.

Mais, depuis que Git a été développé pour Linux pour la première fois, et que de nombreux logiciels open source reposent sur des systèmes compatibles Unix tels que Linux, Mac OS X, FreeBSD, etc., la plupart des communautés open source et leurs outils (y compris les langages de programmation) continuent. suivre ces conventions.

Il y a des raisons techniques qui avaient du sens en 1971, mais à cette époque, il s'agit principalement de conventions et de maintien de la compatibilité avec les outils existants.

22
Nathan Craike

Cela indique simplement que la fin du fichier n'a pas de nouvelle ligne. Ce n'est pas une catastrophe, c'est juste un message pour préciser qu'il n'y en a pas quand on regarde un diff dans la ligne de commande.

18
JohnD

Si vous ajoutez une nouvelle ligne de texte à la fin du fichier existant qui n’a pas encore de caractère de nouvelle ligne, le diff affichera l’ancienne dernière ligne comme ayant été modifiée, même si ce n’était théoriquement pas le cas.

C'est au moins une bonne raison d'ajouter une nouvelle ligne à la fin.

Exemple

Un fichier contient:

A() {
    // do something
}

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

Vous le modifiez maintenant pour

A() {
    // do something
}
// Useful comment

Hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

Le diff de git montrera:

-}
\ No newline at end of file
+}
+// Useful comment.

En d'autres termes, il montre une diff plus grande que conceptuellement survenue. Cela montre que vous avez supprimé la ligne } et ajouté la ligne }\n. C’est en fait ce qui s’est passé, mais ce n’est pas ce qui est conceptuellement , ce qui peut prêter à confusion.

16
Jaseem

Il y a une chose que je ne vois pas dans les réponses précédentes. Un avertissement concernant l'absence de fin de ligne peut être un avertissement lorsqu'une partie d'un fichier a été tronquée. Cela pourrait être un symptôme de données manquantes.

8
user34660

Cette convention a été appliquée dans la pratique car, sur les systèmes d'exploitation de type UNIX, un caractère de nouvelle ligne est traité comme un terminateur de ligne et/ou une limite de message (ceci inclut la canalisation entre les processus, la mise en mémoire tampon de lignes, etc.).

Considérons, par exemple, qu'un fichier comportant uniquement un caractère de nouvelle ligne est traité comme une seule ligne vide. Inversement, un fichier d'une longueur de zéro octet est en fait un fichier vide avec zéro ligne. Ceci peut être confirmé selon la commande wc -l.

Globalement, ce comportement est raisonnable car il n'y aurait pas d'autre moyen de distinguer un fichier texte vide d'un fichier texte avec une seule ligne vide si le caractère \n était simplement un séparateur de ligne plutôt qu'un terminateur de ligne. Ainsi, les fichiers texte valides doivent toujours se terminer par un caractère de nouvelle ligne. La seule exception est si le fichier texte est destiné à être vide (pas de lignes).

6
Leslie Krause

Le problème principal est ce que vous définissez ligne et si la séquence de caractères de fin de ligne fait partie de la ligne ou non. Les éditeurs UNIX (tels que VIM) ou les outils (tels que Git) utilisent une séquence de caractères EOL comme terminaison de ligne; par conséquent, cette partie fait partie de la ligne. C'est similaire à l'utilisation de points-virgules (;) en C et Pascal. En C, le point-virgule se termine, en Pascal, il les sépare.

5
mmcorrelo

Les fichiers sources sont souvent concaténés par des outils (C, C++: fichiers d’en-tête, Javascript: bundlers). Si vous omettez le caractère de nouvelle ligne, vous pouvez introduire de mauvais bugs (où la dernière ligne d'une source est concaténée avec la première ligne du fichier source suivant). Espérons que tous les outils de concaténation de code source insèrent une nouvelle ligne entre les fichiers concaténés, mais cela ne semble pas toujours être le cas.

Le noeud du problème est le suivant: dans la plupart des langues, les nouvelles lignes ont une signification sémantique et la fin de fichier n'est pas une alternative définie par le langage pour le caractère de nouvelle ligne. Vous devez donc terminer chaque déclaration/expression par un caractère de nouvelle ligne - y compris le dernier.

4
Doug Coburn

Cela pose effectivement un problème, car les fins de ligne sont automatiquement modifiées et ne modifient pas les fichiers. Voir ce post pour la résolution.

git remplaçant LF par CRLF

3
Brian Blum

Votre fichier d'origine n'avait probablement aucun caractère de nouvelle ligne.

Cependant, certains éditeurs comme gedit dans Linux ajoutent silencieusement une nouvelle ligne à la fin du fichier. Vous ne pouvez pas vous débarrasser de ce message en utilisant ce type d'éditeurs.

Ce que j’ai essayé de surmonter, c’est d’ouvrir le fichier avec éditeur de code de Visual Studio

Cet éditeur affiche clairement la dernière ligne et vous pouvez supprimer la ligne à votre guise.

2
Berkay92

Pour ce qui en vaut la peine, je l’ai rencontré lorsque j'ai créé un projet IntelliJ sur un Mac, puis que je l'ai déplacé sur ma machine Windows. Je devais ouvrir manuellement chaque fichier et modifier le paramètre d'encodage en bas à droite de la fenêtre IntelliJ. Cela n'arrivera probablement pas à la plupart des lecteurs qui lisent cette question, mais cela aurait pu me faire économiser quelques heures de travail ...

0
Lou Morda