I have a executable shell script name project2. Following is one of the instruction my teacher gave me on the project.
This script must accept at least one
command line parameter: the directory
where its output is to be placed. If
that directory is not given on the
command line, the script should use a
reasonable default directory.
Can you please tell me how can I make my script accept a command line. I haven't done anything like that before. Any help would be greatly appreciated. Thanks a lot.
For bash, command line parameters are stored in $1, $2, and so on, while $# will give you the count. In addition, shift can be used to shift them all "left" by one position and drop the count.
The following script is a good starting point for understanding how the parameters work:
echo $#
while [[ $# -gt 0 ]] ; do
echo "$1"
shift
done
When you run it with:
./myprog.sh hello there my name is "pax diablo"
the output is:
6
hello
there
my
name
is
pax diablo
The basic idea of your assignment is:
check the parameter count to see if it's zero.
if it is zero, set a variable to some useful default.
if it isn't zero, set that variable based on the first parameter.
do whatever you have to do with that variable.
Take a look at this section of Advanced Bash Scripting guide.
I recommend you to read whole guide.
Related
I am attempting to write a shell script that will take a file name with a wildcard, find all files matching that pattern in current directory, and copy them. My problem is every time I try and use a variable only the first match echo's and thats it.
./copyfiles.ksh cust*.txt
#! /usr/bin/ksh
IN_FILE=${1}
for file in $IN_FILE
do
echo "$file"
done
cust1.txt
This seems to only match the first one even though cust1.txt, cust2.txt, and cust3.txt all exist and when I run it with for file in cust*.txt it works.
The shell expands your argument of "cust*.txt" to a list then passes the list to your script, which then only processes $1 which is cust1.txt.
You want to use $# which will process all arguments passed:
#! /usr/bin/ksh
for file in "$#"
do
echo "$file"
done
I believe there is a limit to how many arguments can be passed this way though. How many files are you having to process? Make sure your version of the shell can handle the number of arguments you are likely to process. If I recall you may need a solution utilizing xargs but I'm a tad rusty to help with that.
In ./copyfiles.ksh cust*.txt the files cust*.txt will be expanded first.
When you do not want to change your copyfiles.ksh script. call it with
./copyfiles.ksh "cust*.txt"
You can also change your script, with something like
IN_FILE="$#" # INFILES would be a better name
I have a simple python script that takes a value from input and displays it like so:
x = raw_input ("say something:")
print x
I would like to run this exact program through a bash script and pass some parameter to the script so that it can be printed out on the screen? How would I go about doing this with the bash programming language?
p.s. I know about sys.argv, but I am looking for a bash based solution because I want to also be able to use this solution to pass values to command line programs where I may not necessarily be able to access the source code.
Use positional parameters for this
#!/bin/bash
echo "Your first arguement : $1" # Simlarly $2, $3 & so
echo "Whole arguements to the script : $#"
echo "Argument Count : ${##}"
And run it like :
./script "xxmbabanexx" # here you have only one argument
For a quick reference , check [ this ]. For a complete reference, check the bash manpage, ie do
man bash
in the terminal and scroll down to Positional Parameters and then check Special Parameters section just below that.
Here is what it finally took to get my code in my makefile to work
Line 5 is the question area
BASE=50
INCREMENT=1
FORMATTED_NUMBER=${BASE}+${INCREMENT}
all:
echo $$((${FORMATTED_NUMBER}))
why do i have to add two $ and two (( )) ?
Formatted_Number if i echo it looks like "50+1" . What is the logic that make is following to know that seeing $$(("50+1")) is actually 51?
sorry if this is a basic question i'm new to make and dont fully understand it.
First, whenever asking questions please provide a complete example. You're missing the target and prerequisite here so this is not a valid makefile, and depending on where they are it could mean very different things. I'm assuming that your makefile is something like this:
BASE=50
INCREMENT=1
FORMATTED_NUMBER=${BASE}+${INCREMENT}
all:
echo $$((${FORMATTED_NUMBER}))
Makefiles are interesting in that they're a combination of two different formats. The main format is makefile format (the first five lines above), but inside a make recipe line (that's the last line above, which is indented with a TAB character) is shell script format.
Make doesn't know anything about math. It doesn't interpret the + in the FORMATTED_NUMBER value. Make variables are all strings. If you want to do math, you have to do it in the shell, in a shell script, using the shell's math facilities.
In bash and other modern shells, the syntax $(( ...expression... )) will perform math. So in the shell if you type echo $((50+1)) (go ahead and try it yourself) it will print 51.
That's why you need the double parentheses ((...)): because that's what the shell wants and you're writing a shell script.
So why the double $? Because before make starts the shell to run your recipe, it first replaces all make variable references with their values. That's why the shell sees 50+1 here: before make started the shell it expanded ${FORMATTED_NUMBER} into its value, which is ${BASE}+${INCREMENT}, then it expanded those variables so it ends up with 50+1.
But what if you actually want to use a $ in your shell script (as you do here)? Then you have to tell make to not treat the $ as introducing a make variable. You do this by doubling it, so if make sees $$ then it does not think that's a make variable, and sends a single $ to the shell.
So for the recipe line echo $$((${FORMATTED_NUMBER})) make actually invokes a shell script echo $((50+1)).
You can use this in BASH:
FORMATTED_NUMBER=$((BASE+INCREMENT))
Is using non BASH use:
FORMATTED_NUMBER=`echo "$BASE + $INCREMENT" | bc`
I am trying to write a simple shell-script that prints out the first parameter if there is one and prints "none" if it doesn't. The script is called test.sh
if [$1 = ""]
then
echo "none"
else
echo $1
fi
If I run the script without a parameter everything works. However if I run this command source test.sh -test, I get this error -bash: [test: command not found before the script continues on and correctly echos test. What am I doing wrong?
you need spaces before/after '[',']' chars, i.e.
if [ "$1" = "" ] ; then
#---^---------^ here
echo "none"
else
echo "$1"
fi
And you need to wrap your reference (really all references) to $1 with quotes as edited above.
After you fix that, you may also need to give a relative path to your script, i.e.
source ./test.sh -test
#------^^--- there
When you get a shell error message has you have here, it almost always helps to turn on shell debugging with set -vx before the lines that are causing your trouble, OR very near the top your script. Then you can see each line/block of code that is being executed, AND the value of the variables that the shell is using.
I hope this helps.
I am using the sh 3.2 in Mac Os X. I have a file test.conf
config1="Configuration 1"
config2="a lot of text"
config3=...
So I only need to get the config1= and config2= parameter. How can I set a variable, that I can do this:
> echo $variable
Configuration 1
So simple, but I am not doing it work.
the sommand you are looking for is source
source test.conf
echo $config1 #echoes Configuration 1
if you need to have config1 in variable, add
varible=$config1
At a rough guess...
export `grep 'config1=' /your/config/file`
export `grep 'config2=' /your/config/file`
But remember if you put this in a shell script file, then you'll need to eval the file rather than execute it to set the variables in the current shell instance.
You could do this:
variable=`sed -n 's/^config1=//p'`
Or if you are attempting to evaluate certain parts of your file, try something like
eval `grep ^config1= test.conf`
to have config1=Configuration 1 evaluated by the current shell. (With the example you provided, this will cause a syntax error, because the value cannot contain unquoted whitespace.)
I generally recommend beginners to stay away from backticks, but this is a situation where they are a good answer.