I am maintaining an existing shell script which assigns a command to a variable in side a shell script like:
MY_COMMAND="/bin/command -dosomething"
and then later on down the line it passes an "argument" to $MY_COMMAND by doing this :
MY_ARGUMENT="fubar"
$MY_COMMAND $MY_ARGUMENT
The idea being that $MY_COMMAND is supposed to execute with $MY_ARGUMENT appended.
Now, I am not an expert in shell scripts, but from what I can tell, $MY_COMMAND does not execute with $MY_ARGUMENT as an argument. However, if I do:
MY_ARGUMENT="itworks"
MY_COMMAND="/bin/command -dosomething $MY_ARGUMENT"
It works just fine.
Is it valid syntax to call $MY_COMMAND $MY_ARGUMENT so it executes a shell command inside a shell script with MY_ARGUMENT as the argument?
With Bash you could use arrays:
MY_COMMAND=("/bin/command" "-dosomething") ## Quoting is not necessary sometimes. Just a demo.
MY_ARGUMENTS=("fubar") ## You can add more.
"${MY_COMMAND[#]}" "${MY_ARGUMENTS[#]}" ## Execute.
It works just the way you expect it to work, but fubar is going to be the second argument ( $2 ) and not $1.
So if you echo arguments in your /bin/command you will get something like this:
echo "$1" # prints '-dosomething'
echo "$2" # prints 'fubar'
Related
I have a main_script.sh which will call sub_script.
I have a variable in sub_script which i would like to access in main script
I tried "export" and "env" with the variable but when i'm trying to echo it in main_script i'm not getting values.
for example:
sub_script.sh
export a=hello
echo $a
main_script.sh
$PGMHOME/sub_script.sh > output_file
echo $a
FYI : sub_script.sh is executing properly because I'm getting value of 'a' in output_file
But when I'm echoing the value of a in main_script, I'm not getting it.
p.s : I know I can assign the variable directly in main_sript.sh but this is just an example and i have big processing done in sub_script.sh
Environments (export-ed variables) are passed only "downwards" (from parent to child process), not upwards.
This means that if you want to run the sub-script from the main-script as a process, the sub-script must write the names-and-values somewhere so that the parent process (the main script) can read and process them.
There are many ways to do this, including simply printing them to standard output and having the parent script eval the result:
eval $(./sub_script)
There are numerous pitfalls to this (including, of course, that the sub-script could print rm -rf $HOME and the main script would execute that—of course the sub-script can simply do that directly, but it's even easier to accidentally print something bad than to accidentally do something bad, so this serves as an illustration). Note that the sub-script must carefully quote things:
#! /bin/sh
# sub-script
echo a=value for a
When evaled, this fails because value for a gets split on word boundaries and evals to running for a with a=value set. The sub-script must use something more like:
echo a=\'value for a\'
so that the main script's eval $(./sub_script) sees a quoted assignment.
If the sub-script needs to send output to standard output, it will need to write its variable settings elsewhere (perhaps to a temporary file, perhaps to a file descriptor set up in the main script). Note that if the output is sent to a file—this includes stdout, really—the main script can read the file carefully (rather than using a simple eval).
Another alternative (usable only in some, not all, cases) is to source the sub-script from the main script. This allows the sub-script to access everything from the main script directly. This is usually the simplest method, and therefore often the best. To source a sub-script you can use the . command:
#! /bin/sh
# main script
# code here
. ./sub_script # run commands from sub_script
# more code here
Parameters to script are passed like $1, $2 etc. You can call main_script.sh from sub_script.sh and call main_script.sh again.
main_script.sh
#!/bin/sh
echo "main_script"
./sub_script.sh "hello world!"
sub_script.sh
#!/bin/sh
if [ "${1}" = "" ]; then
echo "calling main_script"
./main_script.sh
else
echo "sub_script called with parameter ${1}"
fi
./main_script.sh
calling main_script
main_script
sub_script called with parameter hello world!
I have a script which has several input files, generally these are defaults stored in a standard place and called by the script.
However, sometimes it is necessary to run it with changed inputs.
In the script I currently have, say, three variables, $A $B, and $C. Now I want to run it with a non default $B, and tomorrow I may want to run it with a non default $A and $B.
I have had a look around at how to parse command line arguments:
How do I parse command line arguments in Bash?
How do I deal with having some set by command line arguments some of the time?
I don't have enough reputation points to answer my own question. However, I have a solution:
Override a variable in a Bash script from the command line
#!/bin/bash
a=input1
b=input2
c=input3
while getopts "a:b:c:" flag
do
case $flag in
a) a=$OPTARG;;
b) b=$OPTARG;;
c) c=$OPTARG;;
esac
done
You can do it the following way. See Shell Parameter Expansion on the Bash man page.
#! /bin/bash
value=${1:-the default value}
echo value=$value
On the command line:
$ ./myscript.sh
value=the default value
$ ./myscript.sh foobar
value=foobar
Instead of using command line arguments to overwrite default values, you can also set the variables outside of the script. For example, the following script can be invoked with foo=54 /tmp/foobar or bar=/var/tmp /tmp/foobar:
#! /bin/bash
: ${foo:=42}
: ${bar:=/tmp}
echo "foo=$foo bar=$bar"
I want to write a script that will change to different directories depending on my input. something like this:
test.sh:
#!/bin/bash
ssh machine001 '(chdir ~/dev$1; pwd)'
But as I run ./test.sh 2 it still goes to ~/dev. It seems that my argument gets ignored. Am I doing anything very stupid here?
Bash ignores any variable syntax inside the single-quoted(') strings. You need double quotes(") in order to make a substitution:
#!/bin/bash
ssh machine001 "(chdir ~/dev$1; pwd)"
The parameter is enclosed in single quotes, so it isn't expanded on the local side. Use double-quotes instead.
#!/bin/bash
ssh machine001 "chdir ~/dev$1; pwd"
There's no need for the (...), since you are only running the pair of commands then exiting.
Hi I am new to shell script. I want to pass an argument to a shell script. I know how to do the same.I have written a simple shell script
#!/bin/bash
parameter=$1
whatispased=${parameter:-"nothing"}
echo $whatispassed
If something is passed as the first argument, it is printed else "nothing" is printed. I have seen some people writing.
parameter=${1,,}
i tried replacing the first line with the one above, but i am getting a bad substitution error. Any help is appreciated.
First you can reduce this to:
#!/bin/bash
whatispassed=${1:-"nothing"}
echo $whatispassed
or even:
#!/bin/bash
echo ${1:-"nothing"}
For ${parameter,,pattern} look into Shell Parameter Expansion
For more on bash or shell scripting, see info:bash and https://stackoverflow.com/q/6798269/1741542.
i have unix shell script which is need to be run like below
test_sh XYZ=KLMN
the content of the script is
#!/bin/ksh
echo $XYZ
for using the value of XYZ i have do set -k before i run the script.
is there a way where i can do this without doint set -k before running the script. or is there something that i can do in the script where i can use value of the parameter given while running the script in the below way
test_sh XYZ=KLMN
i am using ksh.
Any help is appreciated.
How about running this?
XYZ=KLMN ./test_sh //running from directory where test_sh is
If your script needs no other arguments, a quick and dirty way do to it is to put
eval "$#"
at the start of your script. This will evaluate the command line arguments as shell commands. If those commands are to assign a shell/environment variable, then that's what it will do.
It's quick-and-dirty since anything could be put on the command line, causing problems from a syntax error to a bad security hole (if the script is trusted).
I'm not sure if "$#" means the same in ksh as it does in bash - using just $* (without quotes) would work too, but is even dirtier.
It looks like you are trying to use the environment variable "INSTANCE" in your script.
For that, the environment variable must be set in advance of executing your script. Using the "set" command sets exportable environment variables. Incidentally, my version of ksh dates from 1993 and the "-k" option was obsolete back then.
To set an environment variable so that it is exported into spawned shells, simply use the "export" command like so:
export INSTANCE='whatever you want to put here'
If you want to use a positional parameter for your script -- that is have the "KLMN" value accessed within your script, and assuming it is the first parameter, then you do the following in your script:
#!/bin/ksh
echo $1
You can also assign the positional parameter to a local variable for later use in your script like so:
#!/bin/ksh
param_one=$1
echo $param_one
You can call this with:
test_sh KLMN
Note that the spacing in the assignment is important -- do not use spaces.
I am tring this option
#!/bin/ksh
echo $1
awk '{FS="=";print $2}' $1
and on the command line
test_sh INSTANCE=LSN_MUM
but awk is failing.is there any problem over here?
Probably #!/bin/ksh -k will work (untested).