6

This question already has an answer here:

I have this script:

echo $HOME
cd $HOME
cd /
cd /usr/local/src/

When I run it like this

. script.sh

I get this output:

/home/user
: No such file or directory
: No such file or directory
: No such file or directory

If I run it normally (I added #!/bin/bash before the first line)

sh script.sh

I get this output:

: not found.sh: 2: script.sh
/home/user
script.sh: 3: Can't cd to /home/user
script.sh: 4: Can't cd to /
script.sh: 5: Can't cd to /usr/local/src/

The script was run from $HOME directory each time. If I run each command one by one from shell, it executed without problems (invoking cd $HOME from within $HOME simply didn't change directory).

What must I do to make this work?

marked as duplicate by Gilles bash May 19 '16 at 21:18

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • What is your default shell? Is this the exact script you are using? None of these errors make sense. As a side note, there is no reason for the #!/bin/bash if you run the script as sh script.sh. – terdon Sep 8 '14 at 16:04
  • 3
    Did you import that script from a Windows machine? If that's case try to convert it to UNIX format with the dos2unix command. – Emmanuel Sep 8 '14 at 16:10
16

You have CR (^M) characters in your script. Convert it to have Unix end-of-lines (only LF). In a portable way:

tr -d '\r' < your_script > output_script

Some explanations based on Olivier Dulac's comment about what happened with CR characters: First, in the shell language, the CR character is not regarded as a special character, e.g. not regarded as a space and not ignored. I write it as ^M below.

  • In the echo $HOME^M line, the content of $HOME followed by ^M followed by a new line was output. Outputting the CR character put the cursor on the first column, but since it was immediately followed by a newline, this had no visible effect.

  • In the cd $HOME^M line, since there is no space between $HOME and the CR character, they are both in the same argument $HOME^M, and this directory does not exist. In the error message, the CR character after $HOME was just output, putting the cursor on the first column, so that the beginning of the line was overwritten by the rest of the message if any: ": No such file or directory" with bash (your first example), nothing with dash (your second example sh script.sh, as #!/bin/bash was ignored since you explicitly asked to run the script with sh, which seems to be dash in your case). The error message completely depends on the shell. For instance, zsh detects that the CR character is not printable and outputs a message like:

    cd: no such file or directory: /usr/local/src/^M

(with the characters "^" and "M", not the CR character), which allows one to detect the cause of the problem much more easily. Otherwise you need to redirect/pipe stderr to some utility that can show special characters such as cat -ve as suggested by Olivier, or to hd, which gives the byte sequence for the stream.

  • How do I do that? I can't enter `\` character in the terminal... Alt Gr + Q doesn't work, which is how I usually type it... – Karlovsky120 Sep 8 '14 at 16:27
  • I have an effin Croatian QWERTZ keyboard. I found backslash, but now I can't find less than... -.- – Karlovsky120 Sep 8 '14 at 16:49
  • If you really can't generate a '\' character, run dos2unix or equivalent (e.g., dd if=script iflag=text > new_script), or delete the carriage returns some other way, there's a last-resort kludge hack: put a space and a # at the end of each line of the script. – G-Man Sep 8 '14 at 16:50
  • 1
    @Karlovsky120 All QWERTZ keyboards have < and > keys. Instead of using alternative commands (dd iflag=text is not standard), you should better learn where they are. – vinc17 Sep 8 '14 at 17:08
  • 1
    +1, but maybe add just an explanation: in linux, the CR (Carriage return) (^M) extra character causes the cursor to return to the beginning of the line. And it is also interpreted as part of the directory names. So it really says something like cd: /^M: No such file or directory and the ^M place cursor at the beginning, so the rest of the message "overwrites" the beginning. In the 2nd example, cursor only comes back to beginning as the last character on the line, therefore it's "invisible" that it does so. try your_script 2>&1 | cat -ve : -v to show special chars, -e to end lines with $ – Olivier Dulac Sep 10 '14 at 7:36
4

If you use set -x you will notice why sourcing the file is failing:

$ . test.sh
+ . test.sh
++ echo $'/home/braiam\r'
/home/braiam
++ cd $'/home/braiam\r'
: No such file or directory
++ cd $'/\r'
: No such file or directory
++ cd $'/usr/local/src/\r'
: No such file or directory

As vinc17 said, just remove the \r part of your script and you will be fine. You can use his solution, or using dos2unix script.sh, also sed -i 's/\r//' script.sh

1

You can use the below command as well to remove the CR characters.

perl -p -i -e "s/\r//g" script.sh

If you are using vi/vim, you could do,

:set ff=unix
1

I had this same problem and I fixed it by converting the EOL characters to UNIX format. An easy way to do it is:

  • Load the file into Notepad++
  • Select all of the text to be converted (Ctrl + A)
  • Edit > EOL Conversion > UNIX
  • Save the file

If already in UNIX format, select another format (Windows) and then back into UNIX

  • How do I install Notepad++ on Debian systems? – Anthon Apr 8 '15 at 17:48
  • I have never done it myself but a quick google search lead to this: sourcedigit.com/… – moerion Apr 13 '15 at 21:59
  • Install Notepad++ using Wine on Linux – Aadishri Sep 7 '17 at 8:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.