40

I have a file that only uses \n for new lines, but I need it to have \r\n for each new line. How can I do this?

For example, I solved it in Vim using :%s/\n/\r\n/g, but I would like to use a script or command-line application. Any suggestions?

I tried looking this up with sed or grep, but I got immediately confused by the escape sequence workarounds (I am a bit green with these commands).

If interested, the application is related to my question/answer here

1

8 Answers 8

48

You can use unix2dos (which found on Debian):

unix2dos file

Note that this implementation won't insert a CR before every LF, only before those LFs that are not already preceded by one (and only one) CR and will skip binary files (those that contain byte values in the 0x0 -> 0x1f range other than LF, FF, TAB or CR).

or use sed:

CR=$(printf '\r')
sed "s/\$/$CR/" file

or use awk:

awk '{printf "%s\r\n", $0}' file

or:

awk -v ORS='\r\n' 1 file

or use perl:

perl -pe 's|\n|\r\n|' file
4
  • 1
    Note that unix2dox won't insert a CR before every LF, only before those LFs that are not already preceded by one (and only one) CR. Sep 1, 2014 at 16:34
  • @StéphaneChazelas: Thanks for the point, added it to my answer.
    – cuonglm
    Sep 1, 2014 at 16:47
  • 1
    The key piece of information for me here was using '\r' with sed does the trick.
    – rkersh
    Jun 16, 2016 at 17:43
  • Won't your perl code add a \r to lines that may already contain that character, resulting in \r\r\n? Apr 16 at 13:12
10

This is exactly what unix2dos does:

$ unix2dos file.txt

That will replace file.txt in-place with a version with CRLF line endings.

If you want to do it with sed, you can insert a carriage return at the end of every line:

sed -e 's/$/\r/' file.txt

This replaces (s) the zero-size area right before the end of the line ($) with \r. To do in-place replacement (like unix2dos does), use sed -i.bak, although that is a non-standard extension - if you don't have it, use a temporary file.

2
  • 4
    Use \r in replacement is not portable. At least, it won't work in Mac OSX.
    – cuonglm
    Sep 1, 2014 at 6:43
  • Note that there are several implementations of unix2dos. You may want to give a link to the home page of a specific implementation (like waterlan.home.xs4all.nl/dos2unix.html as found on Debian) instead of linux.die.net/man which doesn't make it clear which implementation (or version) is documented. Note that there are some u2d, ux2dos, todos commands around as well. Sep 1, 2014 at 16:36
3

If you are doing the conversion on a Unix machine (OS X, Linux), open the file with vi or vim:

$ vim my-file

press the ESC key to ensure that you are not in insert mode, then type

:set ff=dos

or

:set fileformat=dos

This does conversion in place by setting the file format.

To write the file and quit the editor use

:wq

On the command line you can do

$ vi +':w ++ff=dos' +':q' my-file
1
  • thanks for explaining all the steps - for a newbie it makes it much easier to understand what is going on. Apr 19, 2017 at 12:01
3

Doing this with POSIX is tricky:

  • POSIX Sed does not support \r or \15. Even if it did, the in place option -i is not POSIX

  • POSIX Awk does support \r and \15, however the -i inplace option is not POSIX

  • d2u and dos2unix are not POSIX utilities, but ex is

  • POSIX ex does not support \r, \15, \n or \12

To remove carriage returns:

awk 'BEGIN{RS="\1";ORS="";getline;gsub("\r","");print>ARGV[1]}' file

To add carriage returns:

awk 'BEGIN{RS="\1";ORS="";getline;gsub("\n","\r&");print>ARGV[1]}' file
1

A portable shell function that will do this:

u2dos() (set -f; IFS='
'; printf '%s\r\n' $(cat "$1"))

With that you can do:

u2dos file >dosfile
1

In awk you can try

awk '{print $0 "\r"}'

Or

awk -v r=$'\r' '{print $0 r}'

The $'\r' is an example of ANSI-C style quoting as supported by a few shells like ksh93, bash, zsh, mksh and FreeBSD sh and likely to be included in issue 8 of the Single Unix Specification.

It offers a general way to express weird characters, try this, for example:

awk -v r=$'\U0001F608' '{print $0 r}'
1

Using Raku (formerly known as Perl_6)

~$ cat unix2dos.raku
my $fh1 = open $*IN, :r;

#below use :w (write-only) or :x (:x write-only :exclusive i.e. 'no-clobber')
my $fh2 = open $*OUT, :x, nl-out => "\r\n";

for $fh1.lines() { $fh2.put($_) };

$fh1.close;
$fh2.close;

Save the above file to a script (e.g. "unix2dos.raku"), add a shebang line and make it executable--or simply call it at the command line:

~$ raku unix2dos.raku < ends_with_LF.txt > ends_with_CRLF.txt 

Example Input showing Unix line endings with 0a per line:

~$ jot -w '%d' 5 | hexdump -C
00000000  31 0a 32 0a 33 0a 34 0a  35 0a                    |1.2.3.4.5.|
0000000a

Example Output (adds Raku script) to generate DOS line endings with 0d 0a per line:

~$ jot -w '%d' 5 | raku unix2dos.raku | hexdump -C
00000000  31 0d 0a 32 0d 0a 33 0d  0a 34 0d 0a 35 0d 0a     |1..2..3..4..5..|

References:
https://docs.raku.org/language/newline.html
https://raku.org

Example Source:
https://unix.stackexchange.com/a/742732/227738

0
0

You can use GNU sed command:

 sed -i 's/$/\x0D/g' file.txt
  • $ - regex for end of line

  • \x0D - hex value for carriage return in ASCII

~] cat -v file.txt  
line1
line2
line3
line4

~] sed -i 's/$/\x0D/g' file.txt

~] cat -v file.txt             
line1^M
line2^M
line3^M
line4^M

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .