Shell script with comment, command not found when creating variable - shell

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.

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

Why basename can not be used for a variable?

I have the following shell script
#!/bin/bash
echo "$(basename $(pwd))"
MYDIR= "$(basename $(pwd))"
echo "this is ${MYDIR}"
When I execute it I got
mydirectory
./test.sh: line 4: mydirectory: command not found
this is
so eventhough the first line gets my current directory somehow this cannot be assigned to a variable
Why?? and how can I assign correctly the current directory to a variable (not the complete path)
EDIT: After I tried Gilles Quenot answer that works! (Thanks!) I tried mine with a small variation
#!/bin/bash
echo "$(basename $(pwd))"
MYDIR="$(basename $(pwd))"
echo "this is ${MYDIR}"
and now it works! turns out I should not put spaces around the "="!
when you have shell errors, always check your script on https://shellcheck.net/
never put spaces around = in shell
for dir name, use dirname
avoid using UPPER CASE variables, they are reserved for system use
better use already configured $PWD variable:
:
echo "$(basename "$PWD")"
mydir="$(dirname "$PWD")"
echo "this is $mydir"

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

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

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

Resources