15

I'm trying to do the opposite of this question, replacing Unix line endings with Windows line endings, so that I can use SQL Server bcp over samba to import the file. I have sed installed but not dos2unix. I tried reversing the examples but to no avail.

Here's the command I'm using.

sed -e 's/\n/\r\n/g' myfile

I executed this and then ran od -c myfile, expecting to see \r\n where there used to be \n. But there all still \n. (Or at least they appear to be. The output of od overflows my screen buffer, so I don't get to see the beginning of the file).

I haven't been able to figure out what I'm doing wrong. Any suggestions?

Community
  • 1
  • 1
John M Gant
  • 18,970
  • 18
  • 64
  • 82

7 Answers7

17

When faced with this, I use a simple perl one-liner:

perl -pi -e 's/\n/\r\n/' filename

because sed behavior varies, and I know this works.

dlamblin
  • 43,965
  • 20
  • 101
  • 140
  • 1
    Yeah, this is the best portable option. The hand-entered ^M and unreliable \r expansions above are showstoppers. – Andy Ross Oct 05 '09 at 19:14
  • my_stupidity: using this twice creates a lot of '\r\r\n'. to repair I did `perl -pi -e 's/\r\r\n/\r\n/' filename` . Just wondering how to assure in general that a file contains no mixed mode patterns (from the view of should be msdos) like `r\r` or `n\n` – grenix Dec 07 '21 at 16:55
14
  • What is the problem with getting dos2unix onto the machine?
  • What is the platform you are working with?
  • Do you have GNU sed or regular non-GNU sed?

On Solaris, /usr/bin/sed requires:

sed 's/$/^M/'

where I entered the '^M' by typing controlV controlM. The '$' matches at the end of the line, and replaces the end of line with the control-M. You can script that, too.

Mechanisms expecting sed to expand '\r' or '\\r' to control-M are going to be platform-specific, at best.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • This did the trick. I might be able to get dos2unix on there, but I was hoping to use existing software. I'm on AIX. I assume it's the non-GNU version. Now that you mention it I've used the control-v control-m trick in vi before, should have thought of that. Thanks. – John M Gant Oct 05 '09 at 19:02
5

You don't need the -e option.

$ matches the endline character. This sed command will insert a \r character before the end of line:

sed 's/$/\r/' myfile 
mob
  • 117,087
  • 18
  • 149
  • 283
  • 1
    Thanks for the suggestion, but for some reason this just sticks an r at the end of the file. – John M Gant Oct 05 '09 at 18:59
  • According to the info manual to GNU sed: "All the escapes introduced here are GNU extensions, with the exception of `\n'.". – hlovdal Oct 05 '09 at 19:07
  • My fault for not specifying the Unix flavor. I'm using AIX. +1 for being the first to point out that I should be searching for $ instead of \n. – John M Gant Oct 05 '09 at 19:10
1

Just adding a \r (aka ^M, see Jonathan Leffler's answer) in front of \n is not safe because the file might have mixed mode EOL, so then you risk ending up with some lines becomming \r\r\n. The safe thing to do is first remove all '\r' characters, and then insert (a single) \r before \n.

#!/bin/sh
sed 's/^M//g' ${1+"$@"} | sed 's/$/^M/'

Updated to use ^M.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
1
 sed 's/\([^^M]\)$/\0^M/' your_file

This makes sure you only insert a \r when there is no \r before \n. This worked for me.

Da Qi
  • 615
  • 5
  • 10
  • Wrong in so many ways, don't use this answer. This should work however: `sed -r 's/([^\r]|^)$/\1\r/' "your_file"` – Yeti Jun 09 '23 at 11:57
0

Try using:

echo " this is output" > input
sed 's/$/\r/g' input |od -c
Misa Lazovic
  • 2,805
  • 10
  • 32
  • 38
-1

Maybe if you try it this way

cat myfile | sed 's/\n/\r\n/g' > myfile.win

will work, from my understanding your just making the replacements to the console output, you need to redirect output to a file, in this case myfile.win, then you could just rename it to whatever you want. The whole script would be (running inside a directory full of this kind of files):

#!/bin/bash
for file in $(find . -type f -name '*')
do
  cat $file | sed 's/\n/\r\n/g' > $file.new
  mv -f $file.new $file
done 
Juparave
  • 706
  • 5
  • 11