Unix script giving error trying to assign variable? - unix

I'm extremely new to Unix, and this is driving me crazy. I am getting this error:
./lines: line 21: [[: grep -c *.* $3: syntax error: operand expected
(error toke n is ".* $3")
./lines: line 26: [[: grep -c *.* $3: syntax error: operand expected
(error toke n is ".* $3")
When running this script:
#!/bin/bash
#lines <start> <finish> <file> prints lines start-finish of file
if [[ $# != 3 ]]
then echo "Command format: lines <starting line> <end line> <filename>"
exit
fi
tLines='grep -c *.* $3'
start=$1
finish=$2
if [[ $finish -lt $start ]]
then echo "$finish is less than $start. I'll go ahead and reverse those for you."
start=$2
finish=$1
fi
start=$((finish-start+1))
if [[ $tLines -lt $start ]]
then echo "$3 is only $tLines lines - that's less than $start"
exit
fi
if [[ $tLines -lt $finish ]]
then echo "3 is only $tLines line - that's less than $finish"
exit
fi
head -$finish $3 | tail -$start
exit
I have no idea what those errors mean and searching them online have not given me much insight. I appreciate any help!

Seems like you wanted to use command substitution here:
tLines='grep -c *.* $3'
But you used the wrong quotes. The correct ones are the legacy backticks:
tLines=`grep -c *.* $3`
Or the newer form:
tLines=$(grep -c *.* $3)

Related

Unix partial string comparison

I need to compare a string partially to check for a given condition.
Like my $1 will be checked if it has a part of a string BLR
while my file input has $1 entries as BLR21 BLR64 IND23
I only need a true condition when $1 is equal to BLR**
where these stars can be anything.
I used a simple if condition
if($1=="BLR21")
{print $2}
Now this only works when whole BLR21 is there in row.
I need to ckeck not for BLR21 but only BLR.
Please Help
Your question is not great, I hope I understood.
Quick and easy solution
grep BLR input.txt
This will output all the lines in which "BLR" is found, in file input.txt. It will match "BLR" with any prefix and suffix, whatever they might be (spaces, alphanumerical, tabs, ...).
"Complicated" solution
A bit more complicated. It does the same thing, but makes sure input.txt exists, and is in the form of a script.
Input file, input.txt:
BLR21 BLR64 IND23
Your script could be:
#!/bin/bash
#
# Arguments
inputfile="input.txt"
if [[ $# -ne 1 ]]
then
echo "Usage: myscript.bash <STRING>"
exit 1
else
string="$1"
fi
# Validation, and processing...
if [[ ! -f "$inputfile" ]]
then
echo "ERROR: file >>$inputfile<< does not exist."
exit 2
else
grep "$string" "$inputfile"
fi
And to call the script, you do:
./myscript.bash BLR
But really, a simple grep does the job here.
Taking it even further...
#!/bin/bash
#
# Arguments
inputfile="input.txt"
if [[ $# -ne 1 ]]
then
echo "Usage: check.bash <STRING>"
exit 1
else
string="$1"
fi
# Validation, and processing...
if [[ ! -f "$inputfile" ]]
then
echo "ERROR: file >>$inputfile<< does not exist."
exit 2
else
while read -r line
do
if [[ "$line" =~ $string ]]
then
echo "$line"
fi
done <"$inputfile"
fi
Now this one is like going to the moon via mars...
It reads each line of the file, one by one. Then it checks if that line contains the string, using the =~ operator inside the if.
But this is crazy, when a simple grep would do.

Error during OpenStack installation: ./stack.sh:exit_trap:539 echo 'Error on exit'

I am new to OpenStack. While installing devstack on my VM, during the execution of
./stack.sh
using ubuntu 16.04, I am getting the following error:
+lib/etcd3:install_etcd3:121 echo ' /opt/stack/devstack/files/etcd-v3.1.7-linux-arm64.tar.gz'
+lib/etcd3:install_etcd3:123 sha256sum -c /opt/stack/devstack/files/etcd.sha256sum
sha256sum: /opt/stack/devstack/files/etcd.sha256sum: no properly formatted SHA256 checksum lines found
+lib/etcd3:install_etcd3:1 exit_trap
+./stack.sh:exit_trap:521 local r=1
++./stack.sh:exit_trap:522 jobs -p
+./stack.sh:exit_trap:522 jobs=
+./stack.sh:exit_trap:525 [[ -n '' ]]
+./stack.sh:exit_trap:531 '[' -f '' ']'
+./stack.sh:exit_trap:536 kill_spinner
+./stack.sh:kill_spinner:417 '[' '!' -z '' ']'
+./stack.sh:exit_trap:538 [[ 1 -ne 0 ]]
+./stack.sh:exit_trap:539 echo 'Error on exit'
Error on exit
+./stack.sh:exit_trap:540 generate-subunit 1517844452 85 fail
+./stack.sh:exit_trap:541 [[ -z /opt/stack/logs ]]
+./stack.sh:exit_trap:544 /opt/stack/devstack/tools/worlddump.py -d /opt/stack/logs
World dumping... see /opt/stack/logs/worlddump-2018-02-05-152857.txt for details
+./stack.sh:exit_trap:550 exit 1
I also check the worlddump file, but I didn't see nothing strange, for me.
I strictly follow the steps described in this guide: https://docs.openstack.org/devstack/latest/
Could the hardware on which I am working cause this error?
Any tips?
Thanks

Location=$1? what does it mean?

#!/bin/bash
LOCATION=$1
FILECOUNT=0
DIRCOUNT=0
if [ "$#" -lt "1" ]
then
echo "Usage: ./test2.sh <directory>"
exit 0
fi
I don't actually get what the If statement is saying can anyone help me to explain this?Thank you
$1 refers to the first argument of the bash file. In this case, you can pass your directory path by issuing the following command:
# ./test2.sh /path/of/your/directory
#!/bin/bash
LOCATION=$1 #first argument of the script
FILECOUNT=0
DIRCOUNT=0
if [ "$#" -lt "1" ] #if the number of argument(s) ($#) is less than 1
then
echo "Usage: ./test2.sh <directory>"
exit 0
fi
You can read this article for more information about parameter passing.
Hope it helps.
$1 is the first argument that is passed to the bash script. If you start the script like ./test2.sh argument1 argument2 the $1 will refer argument1.
The if-statement checks, if the count of arguments (that's the $#) is smaller than 1, then it will output the usage statement (as it seems you can't run the script without any argument).

if [ $? -ne 0 ] then syntax error then unexpected

I have been trying to execute the following UNIX shell script which is not working.
I am running it by KornShell (ksh).
echo $?;
if [ $? -ne 0 ]
then
failed $LINENO-2 $5 $6
fi
failed()
{
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
This is giving an error saying Syntax error:then unexpected.. Basically I have to check for the last executed ksh script's highest/last statement's return code and if it is not equal to zero I have to call function failed with the given parameters. I tried putting semicolon before then but that also did not work.
Can you please help?
Edit1: Based on the inputs I changed code. Still the same problem exists.
ksh ../prescript/Pre_process $1 $2 $3
rc=$?;
if [[ $rc -ne 0 ]];then
echo "failed";
exit 1;
Edit2:
It is working for the then part by using double squared brackets. I feel I used code of bash script for ksh. I am facing problem in function call of failed. Please let me know appropriate way of function call in ksh for this example
This looks like bash rather than ksh
failed() {
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
if [[ $? -ne 0 ]]
then
failed $LINENO-2 $5 $6
fi
You need to be careful. The first operation on $? will usually clear it so that your if won't work anyway.
You would be better off using:
rc=$?
echo $rc
if [ $rc -ne 0 ]
:
Other than that, it works fine for me:
$ grep 1 /dev/null
$ if [ $? -ne 0 ]
> then
> echo xx
> fi
xx
$ grep 1 /dev/null
$ echo $?;
1
$ if [ $? -ne 0 ]
> then
> echo yy
> fi
$ _
Note the lack of output in the last one. That's because the echo has sucked up the return value and overwritten it (since the echo was successful).
As an aside, you should let us know which UNIX and which ksh you're actually using. My working version is ksh93 under Ubuntu. Your mileage may vary if you're using a lesser version.
It looks like, from your update, your only problem now is the function call. That's most likely because you're defining it after using it. The script:
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
failed()
{
echo Return code was $1
}
produces:
qq.ksh[6]: failed: not found
while:
failed()
{
echo Return code was $1
}
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
produces
Return code was 1
you are missing semicolons at the end of the lines:
if [ $? -ne 0]; then
# …

Find out if a command exists on POSIX system

I want to be able to tell if a command exists on any POSIX system from a shell script.
On Linux, I can do the following:
if which <command>; then
...snip...
fi
However, Solaris and MacOS which do not give an exit failure code when the command does not exist, they just print an error message to STDOUT.
Also, I recently discovered that the which command itself is not POSIX (see http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html)
Any ideas?
command -v is a POSIX specified command that does what which does.
It is defined to to return >0 when the command is not found or an error occurs.
You could read the stdout/stderr of "which" into a variable or an array (using backticks) rather than checking for an exit code.
If the system does not have a "which" or "where" command, you could also grab the contents of the $PATH variable, then loop over all the directories and search for the given executable. That's essentially what which does (although it might use some caching/optimization of $PATH results).
One which utility is available as shell script in the Git repository of debianutils package of Debian Linux. The script seems to be POSIX compatible and you could use it, if you take into account copyright and license. Note that there have been some controversy whether or not and how the which utility should be deprecated; (at time of writing) current version in Git shows deprecation message whereas an earlier version added later removed -s option to enable silent operation.
command -v as such is problematic as it may output a shell function name, an alias definition, a keyword, a builtin or a non-executable file path. On the other hand some path(s) output by which would not be executed by shell if you run the respective argument as such or as an argument for command. As an alternative for using the which script, a POSIX shell function using command -v could be something like
#!/bin/sh
# Argument $1 should be the basename of the command to be searched for.
# Outputs the absolute path of the command with that name found first in
# a directory listed in PATH environment variable, if the name is not
# shadowed by a special built-in utility, a regular built-in utility not
# associated with a PATH search, or a shell reserved word; otherwise
# outputs nothing and returns 1. If this function prints something for
# an argument, it is the path of the same executable as what 'command'
# would execute for the same argument.
executable() {
if cmd=$(unset -f -- "$1"; command -v -- "$1") \
&& [ -z "${cmd##/*}" ] && [ -x "$cmd" ]; then
printf '%s\n' "$cmd"
else
return 1
fi
}
Disclaimer: Note that the script using command -v above does not find an executable whose name equals a name of a special built-in utility, a regular built-in utility not associated with a PATH search, or a shell reserved word. It might not find an executable either in case if there is non-executable file and executable file available in PATH search.
A function_command_exists for checking if a command exists:
#!/bin/sh
set -eu
function_command_exists() {
local command="$1"
local IFS=":" # paths are delimited with a colon in $PATH
# iterate over dir paths having executables
for search_dir in $PATH
do
# seek only in dir (excluding subdirs) for a file with an exact (case sensitive) name
found_path="$(find "$search_dir" -maxdepth 1 -name "$command" -type f 2>/dev/null)"
# (positive) if a path to a command was found and it was executable
test -n "$found_path" && \
test -x "$found_path" && \
return 0
done
# (negative) if a path to an executable of a command was not found
return 1
}
# example usage
echo "example 1";
command="ls"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
command="notpresent"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
echo "example 2";
command="ls"
function_command_exists "$command" && echo "Command: "\'$command\'" exists"
command="notpresent"
function_command_exists "$command" && echo "Command: "\'$command\'" does not exist"
echo "End of the script"
output:
example 1
Command: 'ls' exists
Command: 'notpresent' does not exist
example 2
Command: 'ls' exists
End of the script
Note that even the set -eu that turns -e option for the script was used the script was executed to the last line "End of the script"
There is no Command: 'notpresent' does not exist in the example 2 because of the && operator so the execution of echo "Command: "\'$command\'" does not exist" is skipped but the execution of the script continues till the end.
Note that the function_command_exists does not check if you have a right to execute the command. This needs to be done separately.
Solution with command -v <command-to-check>
#!/bin/sh
set -eu;
# check if a command exists (Yes)
command -v echo > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 1>"
fi
# check if a command exists (No)
command -v command-that-does-not-exists > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
produces:
<handle not found 2>
because echo was found at the first example.
Solution with running a command and handling errors including command not found.
#!/bin/sh
set -eu;
# check if a command exists (No)
command -v command-that-does-not-exist > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
# run command and handle errors (no problem expected, echo exist)
echo "three" && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 3>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 3>"
fi
# run command and handle errors (<handle not found 4> expected)
command-that-does-not-exist && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 4>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 4>"
fi
# run command and handle errors (command exists but <handle other error 5> expected)
ls non-existing-path && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 5>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 5>"
fi
produces:
<handle not found 2>
three
./function_command_exists.sh: 34: ./function_command_exists.sh: command-that-does-not-exist: not found
<handle not found 4>
ls: cannot access 'non-existing-path': No such file or directory
<handle other error 5>
The following works in both bash and zsh and avoids both functions and aliases.
It returns 1 if the binary is not found.
bin_path () {
if [[ -n ${ZSH_VERSION:-} ]]; then
builtin whence -cp "$1" 2> /dev/null
else
builtin type -P "$1"
fi
}

Resources