"let" internal shell command doesn't work in a shell script? - shell

I did
a=1234
let "a=a+1"
on command line and it's fine. But when I do the same in a shell script. It prints out an error that "let: not found".
Here is the script file.
#!/bin/sh
a=1234;
let "a=a+1";
echo "$a";
Thanks,

Do not use let. Use POSIX arithmetic expansion: a=$(($a+1)). This is guaranteed to work in any POSIX-compliant shell.

The problem is likely that /bin/sh is not the same as, or does not behave the same as, your normal shell. For example, when bash is invoked as /bin/sh, it provides a subset of its normal features.
So, you may need to change your shebang line to use a different shell:
#!/bin/bash
or
#!/bin/ksh
You don't need the semi-colons at the ends of the lines.

See at: http://www.hlevkin.com/Shell_progr/hellobash.htm
The correct is:
a=1234;
b=1;
a=`expr $a + $b`;

You should use let a=a+1 without quotes

It's the '$a' of '$a=1234' that is killing you.
The shell does all $ substitutions and THEN evaluates the expression. As a result it saw "=1234" because there was no value to $a.
Use -x to see this.
bash -x your-script

Check your actual shell with the following command in the command line:
echo $SHELL
It will provide a shell name, use that instead of /bin/sh at the first line of your script.

Check the shell name using
echo $SHELL
Change the first line of the script accordingly to
#!/bin/bash
or
#!/bin/ksh
instead of #!/bin/sh.

c=1
d=1
for i in `ls`
do
if [ -f $i ]
then
echo "$c -> $i"
c=`expr $c + 1`
fi
done
c=`expr $c - 1`
echo no. of files $c
for i in `ls`
do
if [ -d $i ]
then
echo "$d -> $i"
d=`expr $d + 1`
fi
done
d=`expr $d - 1`
echo no. of direcrories $d

Related

How can I log the command used to start a bash script? [duplicate]

I know about $*, $#, "$#" and even ${1+"#"} and what they mean.
I need to get access to the EXACT command-line arguments string from a shell script. Please pay attention to the quotes in the example. Anything like "$#" saves parameters but removes quotes and I don't see how to recover from this.
Example:
./my-shell.sh "1 2" 3
And I need to retrieve the EXACT parameter string without any processing:
"1 2" 3
Any idea how to achieve this?
In bash, you can get this from the shell history:
set -o history
shopt -s expand_aliases
function myhack {
line=$(history 1)
line=${line#*[0-9] }
echo "You wrote: $line"
}
alias myhack='myhack #'
Which works as you describe:
$ myhack --args="stuff" * {1..10} $PATH
You wrote: myhack --args="stuff" * {1..10} $PATH
Also, here's a handy diagram:
But I need to exactly reproduce a user-entered command line to be able to programmatically re-execute it in case of failure
You don't need your exact command line for that; you can reconstruct an equivalent (even if not identical!) shell command yourself.
#!/usr/bin/env bash
printf -v cmd_q '%q ' "$#"
echo "Executed with a command identical to: $cmd_q"
...though you don't even need that, because "$#" can be re-executed as-is, without knowing what the command that started it was:
#!/usr/bin/env bash
printf "Program is starting; received command line equivalent to: "
printf '%q ' "$#"
printf '\n'
if [[ ! $already_restarted ]]; then
echo "About to restart ourselves:
exec "$#" # restart the program
fi

variable substitution shell script issue KSH

hello I am trying you achieve the below
i=1
wwn1=hi
i should be able to echo the value in wwn$i. The below code fails. Please help
echo 'wwn$i'
Above prints
wwn$i
it should print 'hi'
I don't have ksh here, so I can not verify the ksh solution
typeset -n x=wwn$i
echo "$x"
# or
eval "echo \$$wwn$i"
With bash you (other readers) could do
x=wwn$i
echo "${!x}"
eval echo \$wwn$i
or
eval echo '$wwn'$i

How to get exact command line string from shell?

I know about $*, $#, "$#" and even ${1+"#"} and what they mean.
I need to get access to the EXACT command-line arguments string from a shell script. Please pay attention to the quotes in the example. Anything like "$#" saves parameters but removes quotes and I don't see how to recover from this.
Example:
./my-shell.sh "1 2" 3
And I need to retrieve the EXACT parameter string without any processing:
"1 2" 3
Any idea how to achieve this?
In bash, you can get this from the shell history:
set -o history
shopt -s expand_aliases
function myhack {
line=$(history 1)
line=${line#*[0-9] }
echo "You wrote: $line"
}
alias myhack='myhack #'
Which works as you describe:
$ myhack --args="stuff" * {1..10} $PATH
You wrote: myhack --args="stuff" * {1..10} $PATH
Also, here's a handy diagram:
But I need to exactly reproduce a user-entered command line to be able to programmatically re-execute it in case of failure
You don't need your exact command line for that; you can reconstruct an equivalent (even if not identical!) shell command yourself.
#!/usr/bin/env bash
printf -v cmd_q '%q ' "$#"
echo "Executed with a command identical to: $cmd_q"
...though you don't even need that, because "$#" can be re-executed as-is, without knowing what the command that started it was:
#!/usr/bin/env bash
printf "Program is starting; received command line equivalent to: "
printf '%q ' "$#"
printf '\n'
if [[ ! $already_restarted ]]; then
echo "About to restart ourselves:
exec "$#" # restart the program
fi

Bash Scripting: greping the parameter

Here is my problem. I have script and I want to make sure that the parameter that is entered when the script is called matches a variable name inside the script.
For example:
./valid foo <- being the script call
#!/bin/bash
PARAM=$1
VAR=/foo/
if grep -c $PARAM == $VAR
then
echo yes
fi
echo no
I am having the worst time using grep, I'm not sure how to use it properly inside of a script and after scouring the internet I think I need some specific feedback on my problem.
Thanks,
EA
This is not robust, but you can do:
if echo "$VAR" | grep -q "$PARAM"; then
It is probably better to simply do:
if test "$VAR" = "$PARAM"; then
If you are trying to match a regex, bash allows:
if [[ "$VAR" =~ "$PARAM" ]]; then
to match the fixed string $VAR against the regex $PARAM. If $VAR is the regex, you should reverse the order of the arguments. (That is, [[ "$PARAM" =~ "$VAR ]].)
You could search inside your script, since the declaration is the name followed by an equal sign:
if egrep "^\s*$PARAM=" $0
then
echo yes
else
echo no
fi
to list variables use
set -o posix ; set
the posix thingie prevents listing of functions.
In order to isolate parameters local to script, run it from the shell and store the result,
then run it from your script and compare output
(set -o posix ; set) >/tmp/variables.before
(set -o posix ; set) >/tmp/variables.after

Shell script with comment, command not found when creating variable

I have the following script which works:
x=10
echo $x
now=$(date +'%Y-%m-%d')
echo $now
However, when I add a comment line at the beginning:
# comment
x=10
echo $x
now=$(date +'%Y-%m-%d')
echo $now
I get the following:
x=10: command not found
x: undefined variable
Why is the addition of the comment causing the script to fail?
if I do the following it works:
x=10
echo $x
now=$(date +'%Y-%m-%d')
# comment here
echo $now
This is a quirk of csh. (Stop using csh!) csh will process a script that does not begin with a '#' using a "standard shell" (quoting from the csh manpage.) When the script begins with '#', csh parses it. Your script is not valid csh.
You should probably add a shebang line to avoid this type of issue. That is, make the first line:
#!/bin/sh
try something like this
#!/bin/sh
#
x=10
echo $x
now=$(date +'%Y-%m-%d')
echo $now
This works on my system (Ubuntu 11.04, 64bit). If that doesn't work then you may have some hidden special character in your file.

Resources