May 16, 2010

bad interpreter no such file

Sometimes shell scripts in Linux gives error like,

bash: ./t1.sh: /bin/sh^M: bad interpreter: No such file or directory

This happens whenever the files are transferred from Windows machine to Linux Machine over network. Reason being different OS uses different line ending characters. Have a look at below table

OS Line End Character
UNIX/Linux LF '\n'
DOS CRLF '\r' and '\n'
MAC CR only '\r'

CR (Carriage Return): return cursor to left margin, (Ctrl-M(^M) or hex 0D) 
LF (Linefeed): move cursor down, (Ctrl-J(^J) or hex 0A)

Combination of cat and sed command can easily solve this issue.

Example:


1. Create a simple shell scripts having (Ctrl+M) character at each line end. Download example code from here and save it as bad_int.sh

#!/bin/sh^M$
^M$
ls -l^M$

2. Make script bad_int.sh executable and run it from shell.

$ chmod +x bad_int.sh
$ ./bad_int.sh
bash: ./bad_int.sh: /bin/sh^M: bad interpreter: No such file or directory
$

3. Use cat and cat -A command to differentiate file contents.

$ cat bad_int.sh
#!/bin/sh

ls -l
$ cat -A bad_int.sh
#!/bin/sh^M$
^M$
ls -l^M$
$

Note: -A argument of cat command displays non printable characters

4. Now, at last remove all occurrence of (^M) character from the script using combination of cat and sed command and redirect its output to bad_int_solved.sh, make script bad_int_solved.sh executable and run it from shell.

$ cat -A bad_int.sh | sed -e 's/\^M\$//g' > bad_int_solved.sh 
$ chmod +x bad_int_solved.sh 
$ ./bad_int_solved.sh 
total 12
-rwxr-xr-x 1 jaymin jaymin 20 Sep 11 14:00 bad_int.sh
-rwxr-xr-x 1 jaymin jaymin 17 Sep 11 14:35 bad_int_solved.sh
-rw-r--r-- 1 jaymin jaymin 19 Sep 11 13:37 so.sh
$

Don't confuse with $ character, it represents line ends for Unix/Linux files.

No comments:

Post a Comment