Sometimes people ask for my help when their shell scripts don’t work. I’ve seen all kinds of problems, ranging from trivial to really, really weird. The one I’m describing in this article is definitely from the weird category, but I’ve seen it quite a few times.
The story goes like this: Someone gets a shell script (or Python, or Perl, or whatever) from a trusted source, usually via email. Then roughly the following happens:
$ chmod 755 my-script $ ./my-script : No such file or directory $ head -1 my-script #! /bin/sh $ ./my-script : No such file or directory $ [ repeated retries, head-scratching ] $ sh my-script [ script works as intended ] $
That’s pretty weird, right? The script has all the right permissions and it works when executing it via
/bin/sh explicitly (“It has no right not to work!!”). Your next steps are usually to strip down the script to a minimum, leaving you with just the first line – which still doesn’t work. The problem becomes obvious when you take a close look at the first line:
$ head -1 my-script | cat -A #! /bin/sh^M $
Note the carriage return (aka CR, aka ASCII 13) at the end of the shebang line (actually at the end of each line). The Linux kernel has no patience for this kind of stuff, it tries to execute a binary called
/bin/sh^M which obviously isn’t there. How did these carriage returns get there you wonder? Usually when you send scripts via some Windows email program.
Fortunately it’s easy to fix if you have the
tofrodos package installed:
$ fromdos my-script $ head -1 my-script | cat -A #! /bin/sh $
If you don’t have
fromdos(1) just use GNU
sed(1) using its fancy in-place editing:
$ sed -i.bak 's,\r$,,' my-script
That’s it. All cleaned up and ready to go.