bash script clobbering variable in echo - bash

I am trying to write a script which reads the hostname of the remote machine and then uses that result in following commands. However, the variable seems to be corrupted or something.
Here is an example of what is happening:
sbaker#eye004:~/workspace/fire_trunk$ REMOTE_HOSTNAME="`ssh $REMOTE 'hostname'`"
sbaker#eye004:~/workspace/fire_trunk$ echo "before $REMOTE_HOSTNAME after"
prints (note the prefixing whitespace):
" after sbaker-PC"
sbaker#eye004:~/workspace/fire_trunk$ echo $REMOTE_HOSTNAME
prints:
"sbaker-PC"
I am wondering why the variable seems unusable and doing weird things (if the after word is longer than the before word, it writes over the top of the characters).
I would expect the first echo to print: "before sbaker-PC after".
Am I just doing something stupid here?
I am using bash on ubuntu 11.

If you put it through od -c you'll see that it's actually returning sbaker-PC\r. The CR at the end is causing it to return the cursor to the first column before echoing the rest of the text, obscuring the "before". As for why it's adding \r, perhaps the file giving the hostname on the other side was saved with DOS line endings (CRLF) instead of *nix line endings (LF).

Related

If-then-else syntax in tcsh

I'm trying to write a simple script in tcsh (version 6.12.00 (Astron) 2002-07-23), but I am getting tripped up by the if-then-else syntax. I am very new to script writing.
This script works:
#!/bin/tcsh -f
if (1) echo "I disagree"
However, this one does not:
#!/bin/tcsh -f
if ( 1 ) then
echo "I disagree"
else
echo "I agree"
endif
For one thing, this code, when run, echoes both statements. It seems to me it should never see the else. For another, the output also intersperses those echoes with three iterations of ": Command not found."
Edited to add: here is the verbatim output:
: Command not found.
I disagree
: Command not found.
I agree
: Command not found.
I know that the standard advice is to use another shell instead, but I am not really in a position to do that (new job, new colleagues, everyone else uses tcsh, want my scripts to be portable).
When I copy-and-paste your script and run it on my system, it correctly prints I disagree.
When I change the line endings to Windows-style, I get:
: Command not found.
I disagree
: Command not found.
I agree
: Command not found.
So, your script very likely has Windows-style line endings. Fix the line endings, and it should work. The dos2unix command is one way to do that (man dos2unix first; unlike most UNIX text-processing commands, it replaces its input file.)
The problem is that tcsh doesn't recognize ^M ('\r') as an end-of-line character. It sees the then^M at the end of the line as a single command, and prints an error message then^M: Command not found. The ^M causes the cursor to return to the beginning of the line, and the rest of the message overwrite the then.

: command not foundop/dominio.sh: line 2:

I'm writing shell scripting for Mac.
Here's my script:
echo "Bienvenido";
/Applications/sdk/platform-tools/adb devices;
sudo /Applications/sdk/platform-tools/adb shell input text 'sp.soporte#gmail.com';
It realize the correct operation, but here is the output :
$ /Users/julien/Desktop/dominio.sh
Bienvenido
: command not foundop/dominio.sh: line 1:
List of devices attached
4790057be1803096 device
: command not foundop/dominio.sh: line 2:
: command not foundop/dominio.sh: line 3:
julien$
If I erase the ; it's not working any more. How should I do????
I think you have Windows-style line endings in your script.
Unix-like systems, including MacOS, use a single LF character to terminate a line; Windows uses a CR-LF pair.
A Windows-style text file looks, on a Unix-like system, like ordinary text with an extra CR character at the end of each line.
Since you have a semicolon at the end of each line, this line:
echo "Bienvenido";
appears to the shell as two commands: echo "Bienvenido" and the CR character (which could actually be a command name if it existed). Note that the echo command was executed.
The shell prints an error message, something like:
/path/to/script: 1: CR: command not found
except that it prints the actual CR (carriage return) character, which moves the cursor to the beginning of the current line, overwriting part of the error message.
Translate your script to use Unix-style line endings. You can use dos2unix for this if you have it. (Read the man page; unlike most filter programs, it overwrites its input file by default.)
Incidentally, you don't need a semicolon on the end of each line of a shell script. Semicolons are needed only when you have multiple commands on one line.
Also, you should probably have a "shebang" as the first line of your script, either #!/bin/sh or #!/bin/bash (use the latter if your script uses bash-specific features).

Unix Script: Appending two variables from a sourced file not working

I can't understand this...
I have .sh file with variables (varsource.sh)
var1=AppleOrange
var2=Mango
Now I am sourcing my varsource.sh in my test.sh script
#!/bin/ksh
. ./varsource.sh
appended=$var1$var2
echo $appended
varloc1=aPPLEoRANGE
varloc2=mANGO
locappended=$varloc1$varloc2
echo $locappended
The output of above script is
MangoOrange
aPPLEoRANGEmANGO
I expected similar behavior when I use variables from sourced file and variables local to my script.
In case of variables from sourced file, the second variable is replacing characters of the first variable instead of appending.
More observations:
. ./varsource.sh
appended=${var1}xx
echo $appended
Output: xxpleOrange
But appending to left end of the variable is working
. ./varsource.sh
appended=xx$var1
echo $appended
Output:xxAppleOrange
Could some one help me understand this behaviour? What should I do to perform the appending in case of sourced variables?
You're on a Windows machine, or the sourced file was created on a Windows machine.
Your line endings are CRLF, carriage return and line feed, DOS/Windows style. The shell treats the carriage return as a regular character, not as part of the 'end of line'.
Remove the carriage returns and all will go back to normal.

Bash Concatenating Strings Improperly

I have a text file with a list of Mercurial repositories in it, in the form:
IDE
Install
InstallShield
I'm writing a bash script to clone/pull/update all the repositories based on the text file. Right now I'm just echoing before I do any actual cloning. If I do:
while read line; do
echo "hg clone" ${MASTER_HG}/${line};
done < Repos.txt
The output is as expected:
hg clone /media/fs02/IDE
hg clone /media/fs02/Install
hg clone /media/fs02/InstallShield
However, if I do:
while read line; do
echo "hg clone" ${MASTER_HG}/${line} ${REPOROOT}/${line};
done < Repos.txt
The output is:
/var/hg/repos/IDE02/IDE
/var/hg/repos/Installnstall
/var/hg/repos/InstallShieldShield
It seems to be replacing the beginning of the string with the end of the string. Is there some kind of character overflow or something going on? My apologies if this is a dumb question, but I'm a relative noob for bash.
Your file has DOS line endings; the \r at the end of $line causes the cursor to return to the beginning of the line, which only affects your output when $line is not the last thing being printed before the newline. You should remove them with something like dos2unix.
You can use something similar to Perl's chomp command to remove a trailing carriage return, if one is present:
# $'\r' is bash-only, but easy to type. For POSIX shell, you'll need to find
# someway of entering ASCII character 13; perhaps Control-V Control-M
line=${line%$'\r'}
Useful if, for whatever reason, you can't (or don't want to) fix the input before reading it.
From the looks of it, ${REPOROOT} might already include ${line}, try echoing ${REPOROOT} by itself and see what you get.

Why is this error happening in bash?

Using cygwin, I have
currentFold="`dirname $0`"
echo ${currentFold}...
This outputs ...gdrive/c/ instead of /cygdrive/c/...
Why is that ?
Your script is stored in DOS format, with a carriage return followed by linefeed (sometimes written "\r\n") at the end of each line; unix uses just a linefeed ("\n") at the end of lines, and so bash is mistaking the carriage return for part of the command. When it sees
currentFold="`dirname $0`"\r
it dutifully sets currentFold to "/cygdrive/c/\r", and when it sees
echo ${currentFold}...\r
it prints "/cygdrive/c/\r...\r". The final carriage return doesn't really matter, but the one in the middle means that the "..." gets printed on top of the "/cy", and you wind up with "...gdrive/c/".
Solution: convert the script to unix format; I believe you'll have the dos2unix command available for this, but you might have to look around for alternatives. In a pinch, you can use
perl -pi -e 's/\r\n?/\n/g' /path/to/script
(see http://www.commandlinefu.com/commands/view/5088/convert-files-from-dos-line-endings-to-unix-line-endings). Then switch to a text editor that saves in unix format rather than DOS.
I would like to add to Gordon Davisson's anwer.
I am also using Cygwin. In my case this happened because my Git for Windows was configured to Checkout Windows-style, commint Unix style line endings.
This is the default option, and was breaking all my cloned shell scripts.
I reran my git setup and changed to Checkout as-is, commit Unix-style line endings which prevented the problem from happening at all.

Resources