Lyte's Blog

Bad code, bad humour and bad hair.

Attack of the Killer Line Endings

If you save a bash script on Windows or email it as a plain text attachment through most Windows email clients, your script will probably stop working.

Why?

Hah! I’m not going to tell you yet, first try it out.

Download the killer_newlines script somewhere and confirm it’s not going to do anything evil:

1
2
3
4
$ curl -s http://lyte.id.au/bash/killer_newlines > killer_newlines
$ cat killer_newlines
#!/bin/bash
echo Hello World

Looks good, it doesn’t do anything dangerous.

Lets run it to make sure it still works:

1
2
3
4
5
6
$ chmod +x killer_newlines
$ ./killer_newlines
bash: ./killer_newlines: /bin/bash^M: bad interpreter: No such file or directory
$ bash killer_newlines
Hello World
: command not found: line 3:

Huh, what just happened?

Unix is just using LF (Line feed, ‘\n’, 0x0A, 10 in decimal) to signify the end of a line, where as Window (and DOS) also use CR (Carriage return, ‘\r’, 0x0D, 13 in decimal). See: Wikipedia’s Newline article for more info.

Bash only copes with Unix style line endings and we’ve introduced non Unix line endings.

But what specifically is happening, why is the error so bizarre?

Bash is trying to execute a command ‘\r’. Given there’s (usually) not a ‘\r’ executable in $PATH it errors.

You may also want to play around with these:

1
2
3
4
5
6
7
$ bash <(printf 'echo Hello World')
Hello World
$ bash <(printf 'echo Hello World\n')
Hello World
$ bash <(printf 'echo Hello World\n\r')
Hello World
: command not found

Weird huh?

Comments