What is the simplest way to remove all the carriage returns \r
from a file in Unix?
-
3Are you talking about either '\r' '\n', or just the nasty '\r's? – v3. Apr 28 '09 at 22:10
-
Related: [grep to find files that contain ^M (Windows carriage return)](http://superuser.com/q/194668/86416). – May 15 '14 at 21:17
-
I think using `tr -d` command is the simplest method, but I am wondering how to remove just **the last carriage return**? – Yarco Apr 04 '22 at 00:18
-
@Yarco: that's actually covered in my answer. Simplest is not always correctest :-) – paxdiablo Jun 15 '23 at 23:02
21 Answers
I'm going to assume you mean carriage returns (CR, "\r"
, 0x0d
) at the ends of lines rather than just blindly within a file (you may have them in the middle of strings for all I know). Using this test file with a CR at the end of the first line only:
$ cat infile
hello
goodbye
$ cat infile | od -c
0000000 h e l l o \r \n g o o d b y e \n
0000017
dos2unix
is the way to go if it's installed on your system:
$ cat infile | dos2unix | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
If for some reason dos2unix
is not available to you, then sed
will do it:
$ cat infile | sed 's/\r$//' | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
If for some reason sed
is not available to you, then ed
will do it, in a complicated way:
$ echo ',s/\r\n/\n/
> w !cat
> Q' | ed infile 2>/dev/null | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
If you don't have any of those tools installed on your box, you've got bigger problems than trying to convert files :-)

- 854,327
- 234
- 1,573
- 1,953
-
16`\r` works only with GNU sed, else you can do this: `sed \`echo "s/\r//"\`` – lapo Feb 24 '11 at 16:47
-
16Neither `sed` nor `echo` recognise `\r` on MacOs. In this case only `printf "\r"` appears to work. – Steve Powell Feb 06 '12 at 16:04
-
Wouldn't the `sed` example _not_ work as expected, given that the match expression includes \n, which is _not_ part of the string matched against? In other words: shouldn't it be `sed 's/\r$//'`? – mklement0 May 08 '12 at 21:29
-
36To elaborate on @steve's comment: On a Mac, use the following: `sed "s/$(printf '\r')\$//"` – mklement0 May 08 '12 at 21:35
-
7To fix issue on mac you can also prefix the single-quote sed string with `$` like so: `sed $'s@\r@@g' |od -c` (but if you would replace with `\n` you would need to escape it) – nhed Apr 12 '13 at 17:25
-
@mklement0, you are correct. I tested this on my linux box and the above sed example doesn't work. It should be: `cat pp/index.php | sed -e 's/\r$//' | od -c` . @paxdiablo, will you update your answer to have the correct sed expression? – Jason Jun 29 '13 at 17:37
-
2I'm not 100% sure, but for OS X, using `CTRL-V + CTRL-M` in place of `\r` looks like it might work. – May 15 '14 at 21:44
-
How to apply it to a complete directory: [/questions/11929461/dos2unix-command-on-entire-directory](http://stackoverflow.com/questions/11929461/dos2unix-command-on-entire-directory) – lepe Dec 19 '14 at 02:12
-
To remove carriage return from all files in a folder recursively: `find . -type f -exec sed -i 's/\r$//' {} \;` – Sawny Jan 12 '15 at 21:16
-
-
1Beware - dos2unix actually overwrites the given file when used with just one argument, unlike most Linux commands. So to use it non-destructively in a pipeline, provide the file you want to convert as stdin, as shown here. – nealmcb Nov 22 '17 at 20:12
-
od -c was really helpful.. I got the '\r' to remove via sed, and had a few extra white spaces still giving me issues. This allowed me to see the issue quickly. – Richard Tyler Miles Dec 02 '19 at 19:32
-
What does `-U` do? I don't see it in the `dos2unix -h` help menu. – Gabriel Staples Jun 15 '23 at 04:43
-
ChatGpt to the rescue! I asked `In the linux command dos2unix, what is the -U option for?` It replied a bunch of great info, including: "If you don't specify the -U option, the command performs the conversion in place, without creating a new output file." I wonder where this info. is in the documentation... – Gabriel Staples Jun 15 '23 at 04:47
-
1@GabrielStaples, another reason not to trust ChatGPT, I suspect :-) Though this answer is old, I'm pretty certain that was the "universal line ending" flag which would handle all input variants. This has probably been removed in the long history of `dos2unix` or it may have been only in a specific platform build ( tended to use CygWin a lot back then, before WSL). In any case, it's not needed for this question so I've removed it. – paxdiablo Jun 15 '23 at 23:01
tr -d '\r' < infile > outfile
See tr(1)

- 51,180
- 9
- 47
- 60
-
4Not great: 1. doesn't work inplace, 2. can replace \r also not at EOL (which may or may not be what you want...). – Tomasz Gandor Jul 09 '14 at 10:33
-
131. Most unixy tools work that way, and it's usually the safest way to go about things since if you screw up you still have the original. 2. The question as stated is to remove carriage returns, not to convert line endings. But there are plenty of other answers that might serve you better. – Henrik Gustafsson Jul 09 '14 at 11:56
-
2If your `tr` does not support the `\r` escape, try `'\015'` or perhaps a literal `'^M'` (in many shells on many terminals, ctrl-V ctrl-M will produce a literal ctrl-M character). – tripleee Aug 25 '14 at 10:55
-
-
4@donlan, late response but you usually use something like: `someProg
out && mv out in`. – paxdiablo Dec 03 '19 at 00:55 -
Thanks @HenrikGustafsson - This works like a gem for `wget` `%0D` 'padding' on Win10 running WSL (Ubuntu). `tr -d '\r' < my_original_file.sh > my_out_file.sh` – semmyk-research Mar 10 '23 at 19:20
The simplest way on Linux is, in my humble opinion,
sed -i.bak 's/\r$//g' <filename>
-i will edit the file in place, while the .bak will create a backup of the original file by making a copy of your file and adding the extension .bak at the end. (You can specify what ever you want after the -i
, or specify only -i
to not create a backup.)
The strong quotes around the substitution operator 's/\r//'
are essential. Without them the shell will interpret \r
as an escape+r and reduce it to a plain r
, and remove all lower case r
. That's why the answer given above in 2009 by Rob doesn't work.
And adding the /g
modifier ensures that even multiple \r
will be removed, and not only the first one.
-
I would advise not to use the `-i` flag since it modifies the original file, and it might be dangerous if you wish to keep it unchanged – zolastro Mar 09 '21 at 09:09
-
2Don't use just -i but -i.bak It will create a backup of the original file with a .bak extention – Angel115 Sep 04 '21 at 09:30
-
If you're matching on `\r$` then `/g` does nothing, because it will only replace the last character before the end of the line. For example `printf 'foo\r\r\r\n' | sed 's/\r$//g' | od -c` keeps two `\r`s. `'s/\r\+$//'` will do what you want (though I don't know that repeated carriage returns is really something to be concerned about). – dimo414 Mar 31 '23 at 17:29
Old School:
tr -d '\r' < filewithcarriagereturns > filewithoutcarriagereturns

- 48,267
- 11
- 78
- 120
There's a utility called dos2unix that exists on many systems, and can be easily installed on most.

- 39,840
- 10
- 78
- 97
-
6
-
Link is now down, please visit [http://dos2unix.sourceforge.net/](http://dos2unix.sourceforge.net/) instead – RyanQuey May 15 '20 at 07:52
sed -i s/\r// <filename>
or somesuch; see man sed
or the wealth of information available on the web regarding use of sed
.
One thing to point out is the precise meaning of "carriage return" in the above; if you truly mean the single control character "carriage return", then the pattern above is correct. If you meant, more generally, CRLF (carriage return and a line feed, which is how line feeds are implemented under Windows), then you probably want to replace \r\n
instead. Bare line feeds (newline) in Linux/Unix are \n
.

- 47,999
- 5
- 74
- 91
-
I am trying to use --> sed 's/\r\n/=/' countryNew.txt > demo.txt which does not work. "tiger" "Lion." – Suvasis Sep 13 '13 at 07:12
-
are we to take that to mean you're on a mac? I've noticed Darwin sed seems to have different commands and feature sets by default than most Linux versions... – jsh Jan 23 '14 at 17:51
-
4FYI, the `s/\r//` doesn't seem to remove carriage returns on OS X, it seems to remove literal `r` chars instead. I'm not sure why that is yet. Maybe it has something to do with the way the string is quoted? As a workaround, using `CTRL-V + CTRL-M` in place of `\r` seems to work. – May 15 '14 at 21:38
-
See the note in answer https://stackoverflow.com/a/41461947/4179032 about this answer! – Leponzo May 01 '23 at 20:01
If you are a Vi user, you may open the file and remove the carriage return with:
:%s/\r//g
or with
:1,$ s/^M//
Note that you should type ^M by pressing ctrl-v and then ctrl-m.

- 611
- 7
- 11
-
3Not great: if the file has CR on every line (i.e. is a correct DOS file), vim will load it with filetype=dos, and not show `^M`-s at all. Getting around this is a ton of keystrokes, which is not what vim is made for ;). I'd just go for `sed -i`, and then `-e 's/\r$//g' to limit the removal to CRs at EOL. – Tomasz Gandor Jul 09 '14 at 10:35
Someone else recommend dos2unix
and I strongly recommend it as well. I'm just providing more details.
If installed, jump to the next step. If not already installed, I would recommend installing it via yum
like:
yum install dos2unix
Then you can use it like:
dos2unix fileIWantToRemoveWindowsReturnsFrom.txt

- 19,579
- 27
- 94
- 160
Once more a solution... Because there's always one more:
perl -i -pe 's/\r//' filename
It's nice because it's in place and works in every flavor of unix/linux I've worked with.

- 787
- 6
- 20

- 61
- 1
- 2
Removing \r
on any UNIX® system:
Most existing solutions in this question are GNU-specific, and wouldn't work on OS X or BSD; the solutions below should work on many more UNIX systems, and in any shell, from tcsh
to sh
, yet still work even on GNU/Linux, too.
Tested on OS X, OpenBSD and NetBSD in tcsh
, and on Debian GNU/Linux in bash
.
With sed
:
In tcsh
on an OS X, the following sed
snippet could be used together with printf
, as neither sed
nor echo
handle \r
in the special way like the GNU does:
sed `printf 's/\r$//g'` input > output
With tr
:
Another option is tr
:
tr -d '\r' < input > output
Difference between sed
and tr
:
It would appear that tr
preserves a lack of a trailing newline from the input file, whereas sed
on OS X and NetBSD (but not on OpenBSD or GNU/Linux) inserts a trailing newline at the very end of the file even if the input is missing any trailing \r
or \n
at the very end of the file.
Testing:
Here's some sample testing that could be used to ensure this works on your system, using printf
and hexdump -C
; alternatively, od -c
could also be used if your system is missing hexdump
:
% printf 'a\r\nb\r\nc' | hexdump -C
00000000 61 0d 0a 62 0d 0a 63 |a..b..c|
00000007
% printf 'a\r\nb\r\nc' | ( sed `printf 's/\r$//g'` /dev/stdin > /dev/stdout ) | hexdump -C
00000000 61 0a 62 0a 63 0a |a.b.c.|
00000006
% printf 'a\r\nb\r\nc' | ( tr -d '\r' < /dev/stdin > /dev/stdout ) | hexdump -C
00000000 61 0a 62 0a 63 |a.b.c|
00000005
%

- 25,870
- 6
- 90
- 122
If you're using an OS (like OS X) that doesn't have the dos2unix
command but does have a Python interpreter (version 2.5+), this command is equivalent to the dos2unix
command:
python -c "import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))"
This handles both named files on the command line as well as pipes and redirects, just like dos2unix
. If you add this line to your ~/.bashrc file (or equivalent profile file for other shells):
alias dos2unix="python -c \"import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))\""
... the next time you log in (or run source ~/.bashrc
in the current session) you will be able to use the dos2unix
name on the command line in the same manner as in the other examples.

- 20,650
- 6
- 81
- 80
you can simply do this :
$ echo $(cat input) > output

- 276
- 3
- 8
-
Don't know why someone gave '-1'. This is a perfectly good answer (and the only one which worked for me). – FractalSpace Jun 22 '15 at 16:43
-
1Oh, sorry, it was me. Wait, look, it really does not work for '\r'! – Viacheslav Rodionov Jun 25 '15 at 13:21
-
1@FractalSpace This is a terrible idea! It completely wrecks all the spacing in the file and leaves all the contents of the file subject to interpretation by the shell. Try it with a file that contains one line `a * b`... – Tom Fenech Jan 28 '16 at 10:37
Here is the thing,
%0d
is the carriage return character. To make it compatabile with Unix. We need to use the below command.
dos2unix fileName.extension fileName.extension

- 12,978
- 3
- 74
- 76
For UNIX... I've noticed dos2unix removed Unicode headers form my UTF-8 file. Under git bash (Windows), the following script seems to work nicely. It uses sed. Note it only removes carriage-returns at the ends of lines, and preserves Unicode headers.
#!/bin/bash
inOutFile="$1"
backupFile="${inOutFile}~"
mv --verbose "$inOutFile" "$backupFile"
sed -e 's/\015$//g' <"$backupFile" >"$inOutFile"

- 1,047
- 9
- 21
If you are running an X environment and have a proper editor (visual studio code), then I would follow the reccomendation:
Visual Studio Code: How to show line endings
Just go to the bottom right corner of your screen, visual studio code will show you both the file encoding and the end of line convention followed by the file, an just with a simple click you can switch that around.
Just use visual code as your replacement for notepad++ on a linux environment and you are set to go.

- 3,554
- 27
- 39
-
Or use `Notepad++`'s command to `Edit / EOL Conversion / Unix (LF)` on your Windows system before copying the file to your Linux system. – Jesse Chisholm Dec 09 '19 at 23:06
cat input.csv | sed 's/\r/\n/g' > output.csv
worked for me

- 5,413
- 2
- 30
- 48

- 407
- 4
- 11
Using sed
sed $'s/\r//' infile > outfile
Using sed
on Git Bash for Windows
sed '' infile > outfile
The first version uses ANSI-C quoting and may require escaping \
if the command runs from a script. The second version exploits the fact that sed
reads the input file line by line by removing \r
and \n
characters. When writing lines to the output file, however, it only appends a \n
character. A more general and cross-platform solution can be devised by simply modifying IFS
IFS=$'\r\n' # or IFS+=$'\r' if the lines do not contain whitespace
printf "%s\n" $(cat infile) > outfile
IFS=$' \t\n' # not necessary if IFS+=$'\r' is used
Warning: This solution performs filename expansion (*
, ?
, [...]
and more if extglob
is set). Use it only if you are sure that the file does not contain special characters or you want the expansion.
Warning: None of the solutions can handle \
in the input file.

- 335
- 3
- 5
I've used python for it, here my code;
end1='/home/.../file1.txt'
end2='/home/.../file2.txt'
with open(end1, "rb") as inf:
with open(end2, "w") as fixed:
for line in inf:
line = line.replace("\n", "")
line = line.replace("\r", "")
fixed.write(line)

- 99
- 10
Though it's a older post, recently I came across with same problem. As I had all the files to rename inside /tmp/blah_dir/ as each file in this directory had "/r" trailing character ( showing "?" at end of file), so doing it script way was only I could think of.
I wanted to save final file with same name (without trailing any character). With sed, problem was the output filename which I was needed to mention something else ( which I didn't want).
I tried other options as suggested here (not considered dos2unix because of some limitations) but didn't work.
I tried with "awk" finally which worked where I used "\r" as delimiter and taken the first part:
trick is:
echo ${filename}|awk -F"\r" '{print $1}'
Below script snippet I used ( where I had all file had "\r" as trailing character at path /tmp/blah_dir/) to fix my issue:
cd /tmp/blah_dir/
for i in `ls`
do
mv $i $(echo $i | awk -F"\r" '{print $1}')
done
Note: This example is not very exact though close to what I worked (Mentioning here just to give the better idea about what I did)

- 89
- 1
- 3
I made this shell-script to remove the \r character. It works in solaris and red-hat:
#!/bin/ksh
LOCALPATH=/Any_PATH
for File in `ls ${LOCALPATH}`
do
ARCACT=${LOCALPATH}/${File}
od -bc ${ARCACT}|sed -n 'p;n'|sed 's/015/012/g'|awk '{$1=""; print $0}'|sed 's/ /\\/g'|awk '{printf $0;}'>${ARCACT}.TMP
printf "`cat ${ARCACT}.TMP`"|sed '/^$/d'>${ARCACT}
rm ${ARCACT}.TMP
done
exit 0