bash catenate strings right to left - bash

I'm debugging this catalina.sh script, at this point:
echo "$CATALINA_HOME"
echo "dot " .
echo "179"
if [ -r "$CATALINA_HOME"/bin/setclasspath.sh ]; then
echo "qui 81"
. "$CATALINA_HOME"/bin/setclasspath.sh
else
echo "185"
echo "Cannot find $CATALINA_HOME/bin/setclasspath.sh"
echo "This file is needed to run this program"
exit 1
fi
output is:
/home/sysadm/2_KNOWAGE/Knowage_6-2_ARES/Knowage-Server-CE
dot .
179
185
/bin/setclasspath.shsadm/2_KNOWAGE/Knowage_6-2_ARES/Knowage-Server-CE
This file is needed to run this program
when actually setclasspath.sh exixts, has write permissions and is where it's supposed to be. So I expect it to be found and run.

The problem is almost certainly to do with line endings. I strongly suspect that CATALINA_HOME is picking up a carriage return character because it has been saved with Windows line endings.
Try running the script through dos2unix to strip the carriage returns.
You might also want to check that your editor is set to use Unix line ends rather than Windows ones.

Related

How to reassign a variable (zsh) when using source utility

The code below tests if the character from a string is matching regex or not.
str=")Y"
c="${str:0:1}"
if [[ $c =~ [A-Za-z0-9_] ]]; then
echo "YES"
output=$c
else
echo "NO"
output="-"
fi
echo $output
I am running it with
source script-name.sh
However, instead of expected printout
NO
-
I am getting an empty line without dash
NO
I understand the issue is somehow around the way i (re-)assign output variable which being me to questions
How to do it properly?
Why source utility has such implication?
UPD_1: it is for Mac's zsh, not bash
UPD_2: the issue occurs only when running script via 'source' utility like "source script-name.sh"
Running with "./script-name.sh" yield correct result as well.
Your problem can be simplified to do on the zsh command line a
echo -
which also doesn't output anything. Similarily, a
echo - x
would output simply x and not - x.
This does not depend on whether or not you are on the Mac. If you would do a
echo - -
or a
=echo -
(the latter using the external program echo) would print a dash.
Therefore, you can change in your script-name.sh a
=echo $output
or a
echo - $output
and you should be fine.
The zshbuiltins man-page explains it, when describing the echo command:
the first dash, possibly following options, is not printed, but everything following it is printed as an argument.
Therefore, in zsh, at least when printing a variable, it is better to also use a lone dash for the safe side.
Your code gives the expected output for bash 4.2.46 on RHEL7.
Are you maybe using zsh?
See echo 'the character - (dash) in the unix command line
EDIT: Ok, if it's zsh, you probably have to use a hack:
if [[ ${output} == '-' ]]; then
echo - ${output}
else
echo ${output}
fi
or use printf:
printf $output"\n"

shell script that determines file type

Having trouble with this problem, i could use some help ....
create a shell script, fileType.sh, that takes a single command line parameter, a file path (might be relative or absolute). The script should examine that file and print a single line consisting of the phrase
Windows ASCII
if the files is an ASCII text file with CR/LF line terminators, or
Something else
if the file is binary or ASCII with “Unix” LF line terminators.
For example:
./fileType.sh ~cs252/Assignments/ftpAsst/d3.dat
Windows ASCII
./fileType.sh /bin/cat
Something else
./fileType.sh fileType.sh
Something else
./fileType.sh /usr/share/dict/words
Something else
Your script should not produce any other output when given a legal path to an existing file. (It may produce anything you like if given an incorrect path to a non-existent file.)
New to Unix, I have some C++ experience.
This is what i have in my script.
#!/bin/sh
grep -r 'Windows ASCII' $1
if $(file == "ASCII TEXT");then
echo Windows ASCII
else
echo Something Else
fi
this is my output:
./fileType.sh: 4: ./fileType.sh: [file: not found
Something Else
#!/bin/sh
grep -r "Windows ASCII" $1
if test "$( file "$1")" = ' ASCII text, with CRFL line terminators'; then
echo Windows ASCII
else
echo Something else
fi
my output now is just Something else when the file I am passing in should give an output of Windows ASCII ...
Your script is trying to execute a command named "[file". That is not what you want. Offering no advice about the advisability of this solution, but the syntax to implement what you seem to want is:
if test "$( file "$1" )" = 'ASCII TEXT'; then
or
if [ "$( file "$1" )" = 'ASCII TEXT' ]; then
[ is a command (whether builtin to the shell or external is irrelevant), which is exactly the same as the command test except that it expects its last argument to be ]. It is a heinous kludge that was an attempt to make the syntax appear as if the brackets are tokens in the shell language. IMO, it is far better to use test as it makes it clear that it is not part of the grammar.
The actual implementation requires that you interpret/test the result of the file return a bit more. William's answer pointed you in that direction. It is a bit unclear whether you are needing a solutions for traditional shell programming (as in Bourne Shell) or whether you are looking for a Bash (or equivalent) solution. Above, I guess the confusion surrounds the use of:
if test "$( file "$1" )" = 'ASCII TEXT'; then
While this will confirm for you that the file is text with lf separators, exclusive of all others, it does not give you a way to tell whether the file contains lines with CRLF line-ends or not (just that it is not 'ASCII TEXT'). To make the exclusive determination whether the file contains CRLF line-ends, you need to test the file output to find CRLF.
Regardless of the shell, the approach is the same. Capture the result of the file command, and test whether the result contains CRLF. The difference between shells is how you accomplish the test. The following examples provide a way to do the testing the Bourne Shell and the same again in Bash (note: there are many ways to accomplish the test in either, this is just one approach in each):
#!/bin/sh
line=`file -b "$1"`
## Bourne Shell
win=0
for i in $line; do # search for CRLF in $line
if test `expr match "$i" "CRLF"` -gt 0 ; then
win=1
break
fi
done
if test "$win" -eq 1 ; then
printf "Windows ASCII\n"
else
printf "Something else\n"
fi
## BASH
if [[ "$line" =~ "CRLF" ]]; then # use substring operator
printf "Windows ASCII\n"
else
printf "Something else\n"
fi
Example with/CRLF:
$ ./Type.sh ../../utl/tst/config.win.ini
Windows ASCII
Windows ASCII
Example with/LF:
$ ./Type.sh ../../utl/tst/config.ini
Something else
Something else

insert binary code as here-doc into shell script?

src:unix programming environment
a shell script ./bundle :it works well with text file but binary code :(
#!/bin/bash
echo '# To unbundle , sh this file'
for i
do
echo "echo $i 1>&2"
echo "cat >$i <<'End of $i'"
cat $i
echo "End of $i"
done
a simple binary file named a.out,
% ./bundle a.out >> out
% chmod u+x out
% ./out # error happened
I got:
./out: line 8: warning: here-document at line 3 delimited by end-of-file (wanted `End of a.out')
yeah, I know the `End of a.out' should be in a seprate line. But I don't know how to implemetate it.
who have some idea?
thx in advance. :D
You can uuencode binary files (as shar does), or do as makeself does, appending the binary as is and reading it out with dd.
(You could obviously also use either of these tools)

Why would a bash script produce the error "command not founde"?

What is wrong with the 5th line in this script ( I have included the snippet that gives me the error and the actual error is listed in the bottom after the code and a link to complete script)?
#! /bin/bash
INSTALLDIR=/usr/local/mapguideopensource
CLEAN_FLAG=0
while [ $# -gt 0 ]; do # Until you run out of parameters...
case "$1" in
-prefix|--prefix)
INSTALLDIR="$2"
shift
;;
-clean|--clean)
CLEAN_FLAG=1
shift
;;
-help|--help)
echo "Usage: $0 (options)"
echo "Options:"
echo " --prefix [installation directory]"
echo " --clean [clean all objects and binaries in Oem]"
echo " --help [Display usage]"
exit
;;
esac
shift # Check next set of parameters.
done
This is the error i get when i run this bash script on linux (REHL5) :
: command not founde 4:
: command not founde 8:
: command not founde 8:
: command not founde 12:
MapGuide Open Source build script for OEM components
'/build_oem.sh: line 17: syntax error near unexpected token `in
'/build_oem.sh: line 17: ` case "$1" in
Please note, that the line number above corresponds to the actual script i am running (i have included a link to that script below)
The original script i am running
From the errors, I'm pretty sure you have carriage returns (aka CR or ^M) at the end of the lines. Windows/DOS text files have carriage return AND linefeed at the end of each line, but unix programs (like bash) just expect a linefeed, and get horribly confused if there's a CR as well. The giveaway is error messages like:
: command not founde 4:
What this really is is ./build_oem.sh: line 4: ^M: command not found, but the carriage return makes the terminal go back to the beginning of the line, and write the end of the message over the beginning of the message:
./build_oem.sh: line 4:
: command not found
|
V
: command not founde 4:
To fix the script, use dos2unix to convert it to proper unix format, then switch to a text editor that saves in unix format.
What choroba says, but also note that your shebang has to be on the first line (which it is not), otherwise it is useless since it's just a plain comment then and it won't necessarily execute under bash.
In the original script, lines 4 and 8 are empty. There is probably some invisible control character on the lines. Try xxd build_oem.sh.

problems with checking for a directory in bash shell script

I am writing a batch-processing script bash that needs to first check to see if a folder exists to know whether or not to run a certain python script that will create and populate the folder. I have done similar things before that do fine with changing the directories and finding directories from a stored variable, but for some reason I am just missing something here.
Here is roughly how the script is working.
if [ -d "$net_output" ]
then
echo "directory exists"
else
echo "directory does not exist"
fi
when I run this script, I usually echo $net_output in the line before to see what it will evaluate to. When the script runs I get my else block of code saying "Directory does not exist", but when I then copy and paste the $net_output directory path that is echoed before into the shell terminal, it changes directories just fine, proving that the directory does in fact exist. I am using Ubuntu 12.04 on a Dell machine.
Thank you in advance for any help that someone can offer. Let me know what additional information I can provide.
The most common cases I've encountered when someone posts a problem like this are the following:
1. The variable contains literal quotes. Bash does not recursively parse quotes, it only parses the "outer" quotes given on the command line.
$ mkdir "/tmp/dir with spaces"
$ var='"/tmp/dir with spaces"'
$ echo "$var"
"/tmp/dir with spaces"
$ [ -d "/tmp/dir with spaces" ]; echo $?
0
$ [ -d "$var" ]; echo $? # equivalent to [ -d '"/tmp/dir with spaces"' ]
1
2. The variable contains a relative path, and the current directory is not what you expected. Check that the value of echo "$PWD" outputs what you expected.
3. The variable was read from a file with dos line endings, CRLF (\r\n). Unix and unix-like systems use just LF (\n) for line endings. If that's the case, the path will contain a CR (\r) at the end. A CR at the end of a line will be "invisible" in a terminal. Check with printf '%q\n' "$var" while debugging the script. See BashFAQ 52 on how to get rid of them.

Resources