Dos2unix
| Fiche express | |
|---|---|
| Domaine | Fins de ligne texte (CRLF/LF) |
| Commandes | dos2unix, unix2dos
|
| Contexte | Fichiers texte édités/transférés entre Windows et Unix/Linux |
| Voir aussi | Sed, Tr (alternative sans paquet dédié) |
dos2unix et unix2dos convertissent les fins de ligne d'un fichier texte entre les conventions Windows (DOS) et Unix/Linux. C'est un problème classique dès qu'un fichier texte (script, fichier de config, CSV…) transite entre les deux mondes : un éditeur Windows ou un transfert FTP en mode binaire peut introduire ou laisser les mauvaises fins de ligne, ce qui casse silencieusement des scripts shell ou des parseurs qui ne s'y attendent pas.
CRLF, LF, CR : les trois conventions
- Windows (CRLF) : chaque ligne se termine par deux caractères,
\r\n— retour chariot (CR,0x0D) suivi d'un saut de ligne (LF,0x0A). C'est l'héritage des machines à écrire/téléscripteurs, repris tel quel par DOS puis Windows. - Unix/Linux (LF) : une seule ligne se termine par
\n(LF,0x0A). Convention de tous les systèmes de type Unix (Linux, BSD, macOS moderne). - Vieux Mac (CR) : les Mac classiques (pré-OS X) terminaient les lignes par
\rseul (CR,0x0D). Obsolète aujourd'hui, mais on peut encore croiser ce format sur de très vieux exports.
Quand un fichier CRLF est ouvert tel quel sous Linux, le \r résiduel apparaît souvent comme ^M en fin de ligne dans un terminal ou un éditeur comme vi.
Commandes de base
dos2unix fichier.txt # convertit Windows (CRLF) -> Unix (LF), modifie le fichier en place
unix2dos fichier.txt # conversion inverse, Unix (LF) -> Windows (CRLF)
dos2unix -n entree.txt sortie.txt # ne pas modifier l'original, écrire le résultat dans un autre fichier
dos2unix -k fichier.txt # conserver la date de modification (mtime) du fichier au lieu de la mettre à jour
Sans -n, la conversion se fait en place (le fichier est réécrit avec les nouvelles fins de ligne) ; sans -k, la date de modification du fichier est rafraîchie comme pour toute écriture normale.
Traitement en masse
dos2unix *.txt # convertit tous les .txt du répertoire courant
dos2unix *.sh *.conf # plusieurs motifs à la fois
find . -name "*.sql" -exec dos2unix {} \; # récursif via find
Symptôme classique : script bash édité sous Windows
Un script shell copié depuis ou édité sous Windows (éditeur qui enregistre en CRLF par défaut) échoue typiquement à l'exécution avec une erreur de ce type :
-bash: ./monscript.sh: /bin/bash^M: bad interpreter: No such file or directory
Le ^M visible dans le message vient du \r resté collé à la fin de la ligne #!/bin/bash : le noyau cherche alors un interpréteur nommé littéralement /bin/bash\r, qui n'existe pas. Il suffit de passer le script dans dos2unix pour corriger le problème :
dos2unix monscript.sh
./monscript.sh
Alternative sans le paquet dédié
Si dos2unix n'est pas installé et qu'on ne peut/veut pas l'ajouter, un sed ou un tr font le même travail pour retirer les \r (voir Sed et Tr) :
sed -i 's/\r$//' fichier.txt # supprime le \r en fin de chaque ligne, modification en place
tr -d '\r' < entree.txt > sortie.txt # supprime tous les \r, en passant par un fichier de sortie
Le tr ne fonctionne pas en place (il lit un flux et écrit sur un autre), contrairement à sed -i ou dos2unix qui réécrivent directement le fichier source.