Convert Mac to Unix Line Endings

Convert Mac to Unix Line Endings

This file will convert Mac line endings to normal Unix/Linux line endings. Most people won't need this -- it's pretty geeky. Mac computers save "plain text files" in one of two formats. Everything is the same except the character(s) that end each line. Sometimes this is not a problem -- if you're only using gui text editor programs on the Mac, for example. Sometimes, if you're uploading scripts, programs, and text files to your web server, you may encounter problems.

This script works on a Unix system (and may work on OS X from Terminal). Use this on text files that were accidentally saved with "Mac Line endings" turned on in your text editor programs. It automatically overwrites the original file, so you should use it on a copy or make sure there's a backup file until you are confident that it works for you. I can't vouch for it not messing up your files. Take precautions.

Create a text file (with Unix line endings --preferably by using Terminal with pico, vi, emacs, etc.) and name it "convertmaclf" (stands for "convert Mac line feeds").

 #!/bin/bash

 for changefile in $*; do
 cat $changefile | sed 's/^M/\
 /g'> $changefile
 done

There are a few tricks here. Type this in the way you see it with the following changes:

  • When it comes time to type the "^M", type control-v control-m.
  • Make sure that the \ is the very last character on the end of the cat/sed line.
  • Make sure the "/g" are the first characters on the following line

Save the file.

Usage examples:

./convertmaclf myfile.php
./convertmaclf myfile.php yourfile.php
./convertmaclf myfile*
./convertmaclf *

(note the last command will try to change "convertmaclf" file also, but it shouldn't cause a problem)

Here is a breakdown of each line in the script:

#!/bin/bash
This tells the operating system that you are running an executable script, and where to find the program that changes text into computer language.
for changefile in $*; do
A 'for' statement creates a loop. "changefile" is a variable -- a container. You'll see it again below. When "changefile" does not have a $ in front, the variable is being assigned -- given a value. I chose the word "changefile" because I'm going to change the file. I could have called it "doberman" and the computer wouldn't care. $* is a special variable. It is a list of parameters given on the command line. Notice that the $ is in front -- that means we're talking about the value(s) it already has, not giving it a new value. The line "for changefile in $*;do" says "take one of $* at a time and assign it to changefile -- then DO the following commands". In other words it will take one of a list of filenames given on the command line and put it through the wringer (the "do" loop) under the name of "$changefile". This variable acts as a placeholder or pointer, temporarily pointing to the file the program is working on.
cat $changefile | sed 's/^M/\
This line uses the program "cat" with the argument of the current file that $changefile is referring to. "cat" reads the file as text and creates a "stream" of text from it. | is called a "pipe" and like a pipe in real life, it is a conduit from one program to another. "sed" is a "stream editor" program and it takes the stream (of text) that comes in through the pipe and performs a complicated set of commands on it. Sed is complex. But here's the brief rundown: s means "substitute". ^M is the special character to represent the line feed -- and it must be typed as control-v control-m when in a unix text editor to get it right. \ at the end of the line represents a different type of linefeed. The rest of the statement is evaluated below. So far we have "substitue the bad line feed with a good line feed."
/g'> $changefile
Since all we want to replace the bad line feed is the good line feed, the substitute command ends as soon as we get to the next line. The "g" means "global" -- we're doing a global replace otherwise it would only substitute once per line of the file. Since *nix does not see the Mac line endings properly, the whole file is one line. Putting "g" means that the replacement will work on the entire file, rather than having to keep running the script over and over to fix the file. There are some other unexplained characters in the sed line. The "/"'s are a character being used to separate the sections. Sometimes I use "!" instead, if my search/replace contain slashes. The instructions for sed need to be in quotes. Sed takes in a stream of text, edits it or manipulates it, then sends it back out as a stream. The ">" is similar to the | pipe. It's called a "redirect" -- and it will take the stream and convert it back into a file -- in this case the file is $changefile -- the same file we started with. This could be dangerous -- this script overwrites your file. So make sure you work from a test copy until you are sure your script is working correctly!
done
When the program sees this instruction, it goes back to the "for" statement and assigns the next value of $* to $changefile -- if there are no values of $* remaining, then it is "done".

Related Websites