Why am I getting "line 1: $' :\r': command not found"?
You have Windows-style line endings.
The no-op command :
is instead read as :<carriage return>
, displayed as :\r
or more fully as $':\r'
.
Run dos2unix scriptname
and you should be fine.
If you don't have dos2unix
, the following should work almost anywhere (and I tested on MobaXterm on Windows):
vi -b filename
Then in vi
, type:
:%s/\r$//
:x
You're good to go.
In vim
, which is what you are using on Cygwin for vi
, there are multiple ways of doing this. Another one involves the fileformat
setting, which can take the values dos
or unix
. Either explicitly change it after loading the file with
set fileformat=unixor explicitly force the file format when writing out the file with
:w +fileformat=unix
For more on this, see the many questions and answers here covering this subject, including:
- Remove ^M character from log files
- Why is vim creating files with DOS line endings?
- How to add a carriage return before every newline?
This is due to the script having been saved by an editor that uses DOS line-endings (such as Notepad++, for example). You will have to remove these from your scripts.
To do this, either use dos2unix
on the script file, or
$ tr -d '\r' <script >script.new && mv script.new script
(this will remove all carriage returns from anywhere in the script)
As for the code in the script:
:
iter=1
if [ -f iter.txt ]
then rm ./iter.txt
fi
This should possibly look something like
iter=1
if [ -f "./$iter.txt" ]; then
rm "./$iter.txt"
fi
This removes the file 1.txt
from the current directory, if it exists. The :
command does nothing (almost) and may be removed. The iter
variable's value should be used as $iter
, and be quoted. And then I'm possibly being more explicit than needs be by using ./
to say that the file needs to be found in the current directory.
If you're planning to turn this into a loop (here, deleting all files 1.txt
, 2.txt
, ..., 10.txt
):
iter=1
while [ "$iter" -le 10 ]; then
if [ -f "./$iter.txt" ]; then
rm "./$iter.txt"
fi
iter=$(( iter + 1 ))
done
Or, if we feel sneaky/lazy,
rm -f {1..10}.txt
in shells that understands brace expansion.
Your scripts have the wrong line-endings. Windows uses CR+LF (\r\n), Unix uses LF (\n), and Classic MacOS uses CR (\r). You'll need to change the line-endings on all affected files, either with a text editor or a standalone tool like dos2unix
.
FTP and version control systems like SVN tend to be able to convert the line endings appropriately, so you might want to look into those options for transferring files in the future.
If these files aren't being transferred, but just used on a single machine, then you'll want to find the settings for line endings in your preferred text editor. Most that are advertised as "for programmers" will have such an option.