ksh syntax error: `if' unmatched - syntax

I'm new in ksh world and I have a problem right now with a script. The script under this lines is into the .profile file of a user in a UNIX machine and when I try to connect whith him i get always the error
home/userTest/.profile: syntax error: `if' unmatched
I don't know how to solve this, because I suppose that this scripts defines the prompt for the connected user, and if I have this error the prompt only shows "$"
I tried the command
ksh -n /home/userTest/.profile
and I get the error always in the last line of the file
#!/bin/ksh
# ksh example
if [[$0 = "ksh"]];
then
bash
exit $?
fi
if [[$0 = "-ksh"]];
then
bash --login
exit $?
fi
export LOGIN=$LOGNAME
#prompt config
PS1="$LOGIN#"$(hostname)":$PWD"
if [["$(id -u)" = "0"]];
then
export PS1="$PS1# "
else
export PS1="$PS1> "
fi
#Alias utile
alias ll="ls -la"
#Set any export here
export PATH_EXAMPLE=/home/userTest
export JAVA_HOME=$PATH_EXAMPLE/games/java/current
export PATH=$JAVA_HOME/bin:$PATH
How can I solve this problem ?
Thanks.

I had the same error. Turned out it was due to DOS format newlines (CR-LF) in my *.sh file created in Windows and then transferred to a Linux server.
Commands to convert DOS format newlines (CR-LF) to UNIX format newlines (LF)
In Windows: using Notepad++, as explained here:
From the "Edit" menu, select "EOL Conversion" -> "UNIX/OSX Format".
You can also set the default EOL in notepad++ via "Settings" -> "Preferences" -> "New Document/Default Directory" then select "Unix/OSX" under the Format box.
In UNIX/Linux: using one of the techniques explained here:
Convert DOS to UNIX using sed command:
sed 's/^M$//' input.txt > output.txt
Convert DOS to UNIX using tr command:
tr -d '\r' < input.file > output.file
Convert DOS to UNIX using this Perl one-liner:
perl -pi -e 's/\r\n/\n/g' input.file
Convert DOS to UNIX using dos2unix command:
dos2unix myfile.txt or dos2unix -b myfile.txt (with a backup)
[ Bonus tip ]
Commands to convert UNIX format newlines (LF) to DOS format newlines (CR-LF)
Convert UNIX to DOS using unix2dos command:
unix2dos myfile.txt or unix2dos -b myfile.txt (with a backup)
Convert UNIX to DOS using sed command:
sed 's/$'"/`echo \\\n\\\r`/" input.txt > output.txt (you need those \\\, you do)

I am using following version
version sh (AT&T Research) 93u+ 2012-08-01
I did not received any syntax error for your above code , though there a problem with your if statement condition instead of
if [[$0 = "-ksh"]]
it should be
if [[ $0 == "-ksh" ]]
or
if [[ $0 = "-ksh" ]]
the latter is obsolete
The complete code is as below
#!/bin/ksh
# ksh example
if [[ $0 = "ksh" ]];
then
bash
exit $?
fi
if [[ $0 == "-ksh" ]];
then
bash --login
exit $?
fi
export LOGIN=$LOGNAME
#prompt config
PS1="$LOGIN#"$(hostname)":$PWD"
if [[ "$(id -u)" == "0" ]];
then
export PS1="$PS1# "
else
export PS1="$PS1> "
fi
#Alias utile
alias ll="ls -la"
#Set any export here
export PATH_EXAMPLE=/home/userTest
export JAVA_HOME=$PATH_EXAMPLE/games/java/current
export PATH=$JAVA_HOME/bin:$PATH
You script may be having some unwanted character , try to look out for then using cat -vte
you can also try command dos2unix filename and then run ksh -n

Related

Whats wrong with my shell script

I want to take a local file and zip it at some other temp location.
Following is my code which is giving error
path="/home/tft/Downloads/ie.js"
temp="/home/tft/Downloads/Temp"
name=$(basename "$path")
echo "$path"
echo "$name"
echo "$temp"
echo "$temp/$name.zip" #Its output is also weird!
zip -r -j "$temp/$name.zip" $path
Getting below output:
/bin/bash test.sh
/home/tft/Downloads/ie.js
ie.js
/home/tft/Downloads/Temp
.zipjstft/Downloads/Temp
zip warning: name not matched: /home/tft/Downloads/ie.js
)zip . -i /home/tft/Downloads/ie.js -r -j /home/tft/Downloads/Temp
Your script is in DOS format. Convert it first to UNIX format:
sed -i 's|\r||' yourscript.sh
Or use dos2unix:
dos2unix yourscript.sh
The error messages you see is caused by having an extra character (carriage return \r) at the end of your values. This happens when your file's format is not UNIX but DOS since DOS' line endings is \r\n where UNIX only has \n.

Bash - Escaping SSH commands

I have a set of scripts that I use to download files via FTP and then delete them from the server.
It works as follows:
for dir in `ls /volume1/auto_downloads/sync-complete`
do
if [ "x$dir" != *"x"* ]
then
echo "DIR: $dir"
echo "Moving out of complete"
# Soft delete from server so they don't get downloaded again
ssh dan#172.19.1.15 mv -v "'/home/dan/Downloads/complete/$dir'" /home/dan/Downloads/downloaded
Now $dir could be "This is a file" which works fine.
The problem I'm having is with special characters eg:
"This is (a) file"
This is a file & stuff"
tend to error:
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `mv -v '/home/dan/Downloads/complete/This is (a) file' /home/dan/Downloads/downloaded'
I can't work out how to escape it so both the variable gets evaluated and the command gets escaped properly. I've tried various combinations of escape characters, literal quotes, normal quotes, etc
If both sides are using bash, you can escape the arguments using printf '%q ', eg:
ssh dan#172.19.1.15 "$(printf '%q ' mv -v "/home/dan/Downloads/complete/$dir" /home/dan/Downloads/downloaded)"
You need to quote the whole expression ssh user#host "command":
ssh dan#172.19.1.15 "mv -v /home/dan/Downloads/complete/$dir /home/dan/Downloads/downloaded"
I'm confused, because your code as written works for me:
> dir='foo & bar (and) baz'
> ssh host mv -v "'/home/dan/Downloads/complete/$dir'" /home/dan/Downloads/downloaded
mv: cannot stat `/home/dan/Downloads/complete/foo & bar (and) baz': No such file or directory
For debugging, use set -vx at the top of the script to see what's going on.
Will Palmer's suggestion of using printf is great but I think it makes more sense to put the literal parts in printf's format.
That way, multi-command one-liners are more intuitive to write:
ssh user#host "$(printf 'mkdir -p -- %q && cd -- "$_" && tar -zx' "$DIR")"
One can use python shlex.quote(s) to
Return a shell-escaped version of the string s
docs

Prevent bash vi multiline collapse

When doing a command line edit in Ubuntu Precise bash how do I prevent vi from converting
for ii in `ls -a`
do
echo $ii
done
to this...
for ii in `ls -a`; do echo $ii; done
Even if I gsub the ';' for a '^M', when I :wq out of the tmp file it reverts to semicolon.
I have "set -o vi" and "EDITOR=vi" in my .bashrc file. Otherwise vanilla install.
This behavior is controlled by the cmdhist and lithist shell options. Try the following command:
shopt -s lithist

Bash syntax error: unexpected end of file

Forgive me for this is a very simple script in Bash. Here's the code:
#!/bin/bash
# june 2011
if [ $# -lt 3 -o $# -gt 3 ]; then
echo "Error... Usage: $0 host database username"
exit 0
fi
after running sh file.sh:
syntax error: unexpected end of file
I think file.sh is with CRLF line terminators.
run
dos2unix file.sh
then the problem will be fixed.
You can install dos2unix in ubuntu with this:
sudo apt-get install dos2unix
Another thing to check (just occured to me):
terminate bodies of single-line functions with semicolon
I.e. this innocent-looking snippet will cause the same error:
die () { test -n "$#" && echo "$#"; exit 1 }
To make the dumb parser happy:
die () { test -n "$#" && echo "$#"; exit 1; }
i also just got this error message by using the wrong syntax in an if clause
else if (syntax error: unexpected end of file)
elif (correct syntax)
i debugged it by commenting bits out until it worked
an un-closed if => fi clause will raise this as well
tip: use trap to debug, if your script is huge...
e.g.
set -x
trap read debug
I got this answer from this similar problem on StackOverflow
Open the file in Vim and try
:set fileformat=unix
Convert eh line endings to unix endings and see if that solves the
issue. If editing in Vim, enter the command :set fileformat=unix and
save the file. Several other editors have the ability to convert line
endings, such as Notepad++ or Atom
Thanks #lemongrassnginger
This was happening for me when I was trying to call a function using parens, e.g.
run() {
echo hello
}
run()
should be:
run() {
echo hello
}
run
I had the problem when I wrote "if - fi" statement in one line:
if [ -f ~/.git-completion.bash ]; then . ~/.git-completion.bash fi
Write multiline solved my problem:
if [ -f ~/.git-completion.bash ]; then
. ~/.git-completion.bash
fi
So I found this post and the answers did not help me but i was able to figure out why it gave me the error. I had a
cat > temp.txt < EOF
some content
EOF
The issue was that i copied the above code to be in a function and inadvertently tabbed the code. Need to make sure the last EOF is not tabbed.
on cygwin I needed:-
export SHELLOPTS
set -o igncr
in .bash_profile . This way I didn't need to run unix2dos
FOR WINDOWS:
In my case, I was working on Windows OS and I got the same error while running autoconf.
I simply open configure.ac file with my NOTEPAD++ IDE.
Then I converted the File with EOL conversion into Windows (CR LF) as follows:
EDIT -> EOL CONVERSION -> WINDOWS (CR LF)
Missing a closing brace on a function definition will cause this error as I just discovered.
function whoIsAnIidiot() {
echo "you are for forgetting the closing brace just below this line !"
Which of course should be like this...
function whoIsAnIidiot() {
echo "not you for sure"
}
I was able to cut and paste your code into a file and it ran correctly. If you
execute it like this it should work:
Your "file.sh":
#!/bin/bash
# june 2011
if [ $# -lt 3 -o $# -gt 3 ]; then
echo "Error... Usage: $0 host database username"
exit 0
fi
The command:
$ ./file.sh arg1 arg2 arg3
Note that "file.sh" must be executable:
$ chmod +x file.sh
You may be getting that error b/c of how you're doing input (w/ a pipe, carrot,
etc.). You could also try splitting the condition into two:
if [ $# -lt 3 ] || [ $# -gt 3 ]; then
echo "Error... Usage: $0 host database username"
exit 0
fi
Or, since you're using bash, you could use built-in syntax:
if [[ $# -lt 3 || $# -gt 3 ]]; then
echo "Error... Usage: $0 host database username"
exit 0
fi
And, finally, you could of course just check if 3 arguments were given (clean,
maintains POSIX shell compatibility):
if [ $# -ne 3 ]; then
echo "Error... Usage: $0 host database username"
exit 0
fi
In my case, there is a redundant \ in the like following:
function foo() {
python tools/run_net.py \
--cfg configs/Kinetics/X3D_8x8_R50.yaml \
NUM_GPUS 1 \
TRAIN.BATCH_SIZE 8 \
SOLVER.BASE_LR 0.0125 \
DATA.PATH_TO_DATA_DIR ./afs/kinetics400 \
DATA.PATH_PREFIX ./afs/kinetics400 \ # Error
}
There is NOT a \ at the end of DATA.PATH_PREFIX ./afs/kinetics400
I just cut-and-pasted your example into a file; it ran fine under bash. I don't see any problems with it.
For good measure you may want to ensure it ends with a newline, though bash shouldn't care. (It runs for me both with and without the final newline.)
You'll sometimes see strange errors if you've accidentally embedded a control character in the file. Since it's a short script, try creating a new script by pasting it from your question here on StackOverflow, or by simply re-typing it.
What version of bash are you using? (bash --version)
Good luck!
Make sure the name of the directory in which the .sh file is present does not have a space character. e.g: Say if it is in a folder called 'New Folder', you're bound to come across the error that you've cited. Instead just name it as 'New_Folder'. I hope this helps.
Apparently, some versions of the shell can also emit this message when the final line of your script lacks a newline.
In Ubuntu:
$ gedit ~/.profile
Then, File -> Save as and set end line to Unix/Linux
I know I am too late to the party. Hope this may help someone.
Check your .bashrc file. Perhaps rename or move it.
Discussion here: Unable to source a simple bash script
For people using MacOS:
If you received a file with Windows format and wanted to run on MacOS and seeing this error, run these commands.
brew install dos2unix
sh <file.sh>
If the the script itself is valid and there are no syntax errors, then some possible causes could be:
Invalid end-of-lines (for example, \r\n instead of \n)
Presence of the byte order mark (BOM) at the beginning of the file
Both can be fixed using vim or vi.
To fix line endings open the file in vim and from the command mode type:
:set ff=unix
To remove the BOM use:
:set nobomb
For those who don't have dos2unix installed (and don't want to install it):
Remove trailing \r character that causes this error:
sed -i 's/\r$//' filename
Details from this StackOverflow answer. This was really helpful.
https://stackoverflow.com/a/32912867/7286223

Can I specify redirects and pipes in variables?

I have a bash script that creates a Subversion patch file for the current directory. I want to modify it to zip the produced file, if -z is given as an argument to the script.
Here's the relevant part:
zipped=''
zipcommand='>'
if [ "$1" = "-z" ]
then
zipped='zipped '
filename="${filename}.zip"
zipcommand='| zip >'
fi
echo "Creating ${zipped}patch file $filename..."
svn diff $zipcommand $filename
This doesn't work because it passes the | or > contained in $zipcommand as an argument to svn.
I can easily work around this, but the question is whether it's ever possible to use these kinds of operators when they're contained in variables.
Thanks!
I would do something like this (use bash -c or eval):
zipped=''
zipcommand='>'
if [ "$1" = "-z" ]
then
zipped='zipped '
filename="${filename}.zip"
zipcommand='| zip -#'
fi
echo "Creating ${zipped}patch file $filename..."
eval "svn diff $zipcommand $filename"
# this also works:
# bash -c "svn diff $zipcommand $filename"
This appears to work, but my version of zip (Mac OS X) required that i change the line:
zipcommand='| zip -#'
to
zipcommand='| zip - - >'
Edit: incorporated #DanielBungert's suggestion to use eval
eval is what you are looking for.
# eval 'printf "foo\nbar" | grep bar'
bar
Be careful with quote characters on that.
Or you should try zsh shell whic allows to define global aliases, e.g.:
alias -g L='| less'
alias -g S='| sort'
alias -g U='| uniq -c'
Then use this command (which is somewhat cryptic for the ones who took a look from behind ;-) )
./somecommand.sh S U L
HTH
Open a new file handle on either a process substitution to handle the compression or on the named file. Then redirect the output of svn diff to that file handle.
if [ "$1" = "-z" ]; then
zipped='zipped '
filename=$filename.zip
exec 3> >(zip > "$filename")
else
exec 3> "$filename"
fi
echo "Creating ${zipped}patch file $filename"
svn diff >&3

Resources