Comment convertir DOS / Windows newline (CRLF) en Unix newline (LF) en script Bash?

Comment puis-je programmer (c'est-à-dire ne pas utiliser vi ) la conversion DOS/Windows newlines en Unix?

les commandes dos2unix et unix2dos ne sont pas disponibles sur certains systèmes. Comment puis-je les émuler avec des commandes comme sed / awk / tr ?

260
demandé sur jww 2010-04-10 19:03:34

21 réponses

vous pouvez utiliser tr pour passer de DOS à Unix; cependant, vous ne pouvez le faire en toute sécurité que si CR apparaît dans votre fichier uniquement comme le premier octet d'une paire de octets CRLF. C'est généralement le cas. Vous utilisez ensuite:

tr -d '5' <DOS-file >UNIX-file

notez que le nom DOS-file est différent du nom UNIX-file ; si vous essayez d'utiliser le même nom deux fois, vous finirez sans données dans le fichier.

Vous ne pouvez pas le faire dans l'autre sens (avec standard "tr").

si vous savez entrer le retour de chariot dans un script ( control-V , control-M pour entrer le contrôle-M), alors:

sed 's/^M$//'     # DOS to Unix
sed 's/$/^M/'     # Unix to DOS

où "^m " est le caractère de contrôle-M. Vous pouvez également utiliser le mécanisme bash ANSI-C citant pour spécifier le retour du chariot:

sed $'s/\r$//'     # DOS to Unix
sed $'s/$/\r/'     # Unix to DOS

cependant, si vous devez faire cela très souvent (plus d'une fois, en gros), il est beaucoup plus raisonnable d'installer les programmes de conversion (par exemple dos2unix et unix2dos , ou peut-être dtou et utod ) et utilise-les.

267
répondu Jonathan Leffler 2015-10-20 20:31:08
tr -d "\r" < file

regardez ici pour des exemples d'utilisation de sed :

# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//'               # assumes that all lines end with CR/LF
sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//'            # works on ssed, gsed 3.02.80 or higher

# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\r`/"            # command line under ksh
sed 's/$'"/`echo \\r`/"             # command line under bash
sed "s/$/`echo \\r`/"               # command line under zsh
sed 's/$/\r/'                        # gsed 3.02.80 or higher

utiliser sed -i pour la conversion sur place, p.ex. sed -i 's/..../' file .

49
répondu ghostdog74 2014-05-11 19:17:22

faire cela avec POSIX est délicat:

  • POSIX Sed ne supporte pas \r ou . Même si elle l'a fait, la mise en place l'option -i n'est pas POSIX

  • POSIX Awk prend en charge \r et , mais le -i inplace option n'est pas POSIX

  • d2u et dos2unix ne sont pas POSIX utilitaires , mais ex est

  • POSIX ex ne prend pas en charge \r , , \n ou

pour enlever le retour du chariot:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

pour ajouter les retours de chariot:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
35
répondu Steven Penny 2016-11-05 18:53:43

ce problème peut être résolu avec des outils standards, mais il y a suffisamment de pièges pour les non-avertis que je vous recommande d'installer la commande flip , qui a été écrite il y a plus de 20 ans par Rahul Dhesi, l'auteur de zoo . Il fait un excellent travail en convertissant les formats de fichier, tout en évitant, par exemple, la destruction inopportune de fichiers binaires, qui est un peu trop facile si vous venez de course autour de modifier chaque CRLF que vous voyez...

19
répondu Norman Ramsey 2010-04-10 22:32:46

en utilisant AWK vous pouvez faire:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

en utilisant Perl vous pouvez faire:

perl -pe 's/\r$//' < dos.txt > unix.txt
17
répondu codaddict 2010-04-10 15:09:28

les solutions publiées jusqu'à présent ne traitent qu'une partie du problème, en convertissant le CRLF DE DOS/Windows en LF D'Unix; la partie manquante est que DOS utilise CRLF comme ligne séparateur , alors que Unix utilise LF comme ligne terminator . La différence est qu'un fichier DOS (habituellement) n'aura rien après la dernière ligne du fichier, alors Qu'Unix le fera. Pour faire la conversion correctement, vous devez ajouter que Final LF (sauf si le fichier est de longueur zéro, i.e. a pas de lignes en tout). Mon incantation préférée pour cela (avec un peu de logique ajoutée pour gérer les fichiers séparés CR de style Mac, et pas les fichiers molest qui sont déjà au format unix) est un peu de perl:

perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/\n/ }; $m=1' PCfile.txt

notez que ceci envoie la version Unixifiée du fichier à stdout. Si vous voulez remplacer le fichier par une version Unixifiée, ajoutez le drapeau -i de perl.

14
répondu Gordon Davisson 2010-04-10 20:20:04

si vous n'avez pas accès à dos2unix , mais pouvez lire cette page, alors vous pouvez copier / coller dos2unix.py d'ici.

#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys

if len(sys.argv[1:]) != 2:
  sys.exit(__doc__)

content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
  content = infile.read()
with open(sys.argv[2], 'wb') as output:
  for line in content.splitlines():
    outsize += len(line) + 1
    output.write(line + '\n')

print("Done. Saved %s bytes." % (len(content)-outsize))

Cross-posté de superuser .

10
répondu anatoly techtonik 2017-03-20 10:04:20

une solution awk encore plus simple avec un programme:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

techniquement '1' est votre programme, B/C awk en a besoin lorsqu'on lui donne l'option.

mise à JOUR : Après avoir revisité cette page pour la première fois depuis longtemps, j'ai réalisé que personne n'avait encore posté de solution interne, donc en voici une:

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
6
répondu nawK 2015-03-01 06:34:24

Super duper facile avec PCRE;

comme un script, ou remplacer $@ avec vos fichiers.

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@

Cela va écraser vos fichiers en lieu!

Je ne recommande de faire cela qu'avec une sauvegarde (contrôle de version ou autre)

6
répondu ThorSummoner 2015-07-30 17:38:45

fait intéressant dans mon Git-bash sur windows sed "" déjà fait le tour:

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

mon avis est que sed les ignore lors de la lecture des lignes d'entrée et écrit toujours les fins de ligne unix sur la sortie.

4
répondu user829755 2017-07-21 09:21:05

pour convertir un fichier en place faire

dos2unix <filename>

à la sortie du texte converti à un fichier différent do

dos2unix -n <input-file> <output-file>

il est déjà installé sur Ubuntu et est disponible sur homebrew

brew install dos2unix

je sais que la question demande explicitement des alternatives à cet utilitaire, mais c'est le premier résultat de recherche google pour "convertir dos aux fins de ligne unix".

4
répondu boris 2018-07-18 00:34:31

cela a fonctionné pour moi

tr "\r" "\n" < sampledata.csv > sampledata2.csv 
3
répondu Santosh 2015-03-12 22:36:01

vous pouvez utiliser Vim programmatically avec l'option-c {commande}:

Dos à Unix:

vim file.txt -c "set ff=unix" -c ":wq"

Unix à dos:

vim file.txt -c "set ff=dos" -c ":wq"
3
répondu Johan Zicola 2018-08-31 10:14:36

TIMTOWTDI!

perl -pe 's/\r\n/\n/; s/([^\n])\z/\n/ if eof' PCfile.txt

D'après @GordonDavisson

il faut considérer la possibilité de [noeol] ...

2
répondu lzc 2016-05-31 17:15:38

pour Mac osx si vous avez homebrew installé [ http://brew.sh/][1]

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

assurez-vous que vous avez fait des copies des fichiers, car cette commande modifiera les fichiers en place. L'option mac-c rend le commutateur compatible avec osx.

1
répondu Ashley Raiteri 2014-05-19 23:25:59

vous pouvez utiliser awk. Réglez le séparateur d'enregistrements ( RS ) sur un regexp qui correspond à tous les caractères newline possibles. Et définissez le séparateur d'enregistrements de sortie ( ORS ) au caractère newline du style unix.

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
1
répondu kazmer 2016-11-06 23:30:31

N'a eu qu'à réfléchir à cette même question (côté Windows, mais également applicable à linux.) Étonnamment, personne n'a mentionné une façon très automatisée de faire la conversion CRLF<->LF pour les fichiers texte en utilisant la bonne vieille option zip -ll (Info-ZIP):

zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip 

NOTE: cela créerait un fichier zip qui conserverait les noms de fichier originaux mais convertirait les fins de ligne en LF. Ensuite unzip extrairait les fichiers comme zip, c'est-à-dire avec leurs noms originaux (mais avec LF-endings), ce qui incite à écraser les fichiers originaux locaux s'il y en a.

extrait pertinent du zip --help :

zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)
1
répondu vmsnomad 2017-06-23 18:37:19

comme une extension de la solution Unix to DOS de Jonathan Leffler, pour convertir en DOS en toute sécurité lorsque vous n'êtes pas sûr de la fin de ligne courante du fichier:

sed '/^M$/! s/$/^M/'

ceci vérifie que la ligne ne se termine pas déjà dans CRLF avant de passer à CRLF.

0
répondu Gannet 2017-01-24 09:07:58

sous Linux, il est facile de convertir ^M (ctrl-M) en *nix newlines (^J) avec sed.

il va quelque chose comme cela sur le CLI, il y aura en fait une rupture de ligne dans le texte. Cependant, l' \ passes ^J le long de sed:

sed 's/^M/\
/g' < ffmpeg.log > new.log

vous obtenez ceci en utilisant ^V (ctrl-V), ^M (CTRL-M) et \ (backslash) comme vous tapez:

sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
0
répondu jet 2018-07-13 13:43:14

j'ai essayé sed 's/^M$//' fichier.txt sur OSX ainsi que plusieurs autres méthodes ( http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing-dos-line-endings ou http://hintsforums.macworld.com/archive/index.php/t-125.html ). Aucun n'a fonctionné, le fichier est resté inchangé (btw Ctrl-V Enter était nécessaire pour reproduire ^M). Finalement, J'ai utilisé TextWrangler. Ce n'est pas strictement une ligne de commande mais ça marche et ça ne se plaint pas.

-3
répondu mercergeoinfo 2013-09-10 13:08:27

Il y a beaucoup de awk/sed/etc réponses en complément (puisque c'est l'un des principaux résultats de la recherche pour cette question):

vous n'avez peut-être pas dos2unix mais avez-vous iconv ?

iconv -f UTF-16LE -t UTF-8 [filename.txt]
-f from format type
-t to format type

ou tous les fichiers d'un répertoire:

find . -name "*.sql" -exec iconv -f UTF-16LE -t UTF-8 {} -o ./{} \;

ceci exécute la même commande, sur tous .fichiers sql dans le dossier courant. -o est le répertoire de sortie Donc vous pouvez l'avoir remplacer les fichiers courants, ou, pour des raisons de Sécurité/Sauvegarde, sortie dans un répertoire séparé.

-5
répondu Katastic Voyage 2017-10-13 00:56:49