I want to run a shell script, run.sh
line_no=$(awk '{x++} END {print x}' #file_name#)
echo $line_no
I want to run the script on different files each time. How can supply the file_name as an argument while running this script?
The arguments to a shell script are $0 (the name of the script), $1 (the first argument passed to the script), $2 (the second argument to the script), etc.
So just use $1 in place of your filename!
Related
I have two files vars.sh and main.sh with the contents:
$ cat vars.sh
#!/bin/bash
fname="$0" # should $0 equal 'vars.sh'?
$ cat main.sh
#!/bin/bash
echo $0
. vars.sh
echo $fname
When I run main.sh I get:
$ ./main.sh
./main.sh
./main.sh
My question is why is $0 inside vars.sh returning main.sh? I read man bash section about $0 but that did not help much.
Sourcing another script involves executing the sourced commands in the current shell. In the current shell, $0 refers to main.sh. You can think of sourcing as similar to "inclusion" or "copy-paste".
However, there does exist a way to get the sourced file name in bash. You can use BASH_SOURCE variable.
If you change vars.sh to:
#!/bin/bash
fname=${BASH_SOURCE[0]}
Then you'll get the sourced file's name as expected.
It is because . (source) includes commands from sourced file, in your case from vars.sh
https://ss64.com/bash/source.html
When a process is started via exec, the first first argument is usually the path to the executable (or whatever the caller decided to pass there as argument). In bash, this argument can be retrieved via $0. In your case, your process is the bash process running main.sh, so that's what is stored there. vars.sh is executed within the same process; hence, $0 is the same.
I'm writing a small script in which I want to set the value of a variable equal to the output of a command. However, the command in question is a call to another script with command-line arguments. I'm using backticks as you normally should in this scenario, but the problem is that the the computer gives an error, in which it tries to interpret the command-line arguments as commands.
#!/bin/bash
filename="$1"
while read p; do
echo "This is the gene we are looking at: ""$p"
lookIn= `./findGeneIn "$p" burgdorferi afzelii garinii hermsii miyamotoi parkeri`
echo "$lookIn"
#grep "$p" "$lookIn""/""prokka_""$lookIn""/*.tsv" | awk '{print $1}'
done < $filename
I'm trying to set variable lookIn equal to the output of ./findGeneIn "$p" burgdorferi afzelii garinii hermsii miyamotoi parkeri, where ./findGeneIn is a script, and the words burgdorferi,...,parkeri are command line arguments for ./findGeneIn.
The issue, is that I get an error saying "burgdorferi: command not found". So it's trying to interpret those arguments as commands. How do I get it to not do that?
lookIn= `./findGeneIn "$p" burgdorferi afzelii garinii hermsii miyamotoi parkeri`
^
Delete the extra space. Assignments must not have spaces around the equal sign.
With the space there, Bash parses the line as var=value command, which runs a command with $var temporarily set to "value". Or in this case, it interprets result of the backticks as a command name and lookIn= as an empty variable assignment.
I want to execute a shell script using usage() in the script.
I have to give three parameters in the usage block like below:
./script_name server_name path flag
How do I write the code block for this?
Finally, I need to read all the three parameters in a line to execute a jar file.
once you pass parameters you can access them with $1, $2 ... $n and $# to get everything at once.
./script_name server_name path flag
In the script code
echo $1, $2, $3
echo "$#" #will print the same thing
I need to read command line arguments. First arg is script name. second one is redirection operator i.e. "<" and third one is input filename. When I tried to use "$#", I got 0. When I used "$*", it gave me nothing. I have to use "<" this operator. My input file consists of all user input data. If I don't use the operator, It asks user for the input. Can someone please help me? Thank you !
Command Line :
./script_name < input_file
Script:
echo "$*" # gave nothing
echo "$#" # gave me 0
I need to read input filename and store it to some variable. Then I have to change the extension of it. Any help/suggestions should be appreciated.
When a user runs:
./script_name <input_file
...that's exactly equivalent to if they did the following:
(exec <input_file; exec ./script_name)
...first redirecting stdin from input_file, then invoking the script named ./script_name without any arguments.
There are operating-system-specific interfaces you can use to get the filename associated with a handle (when it has one), but to use one of these would make your script only able to run on an operating system providing that interface; it's not worth it.
# very, very linux-specific, won't work for "cat foo | ./yourscript", generally evil
if filename=$(readlink /proc/self/fd/0) && [[ -e $filename ]]; then
set -- "$#" "$filename" # append filename to the end of the argument list
fi
If you want to avoid prompting for input when an argument is given, and to have the filename of that argument, then don't take it on stdin but as an argument, and do the redirection yourself within the script:
#!/bin/bash
if [[ $1 ]]; then
exec <"$1" # this redirects your stdin to come from the file
fi
# ...put other logic here...
...and have users invoke your script as:
./script_name input_file
Just as ./yourscript <filename runs yourscript with the contents of filename on its standard input, a script invoked with ./yourscript filename which invokes exec <"$1" will have the contents of filename on its stdin after executing that command.
< is used for input redirection. And whatever is at the right side of < is NOT a command line argument.
So, when you do ./script_name < input_file , there will be zero (0) command line arguments passed to the script, hence $# will be zero.
For your puprpose you need to call your script as:
./script_name input_file
And in your script you can change the extension with something like:
mv -- "$1" "${1}_new_extension"
Edit: This was not what OP wanted to do.
Altough, there is already another spot on answer, I will write this for the sake of completeness. If you have to use the '<' redirection you can do something like this in your script.
while read filename; do
mv -- "$filename" "${filename}_bak"
done
And call the script as, ./script < input_file. However, note that you will not be able to take inputs from stdin in this case.
Unfortunately, if you're hoping to take redirection operators as arguments to your script, you're not going to be able to do that without surrounding your command line arguments in quotes:
./script_name "<input_file"
The reason for this is that the shell (at least bash or zsh) processes the command before ever invoking your script. When the shell interprets your command, it reads:
[shell command (./script_name)][shell input redirection (<input_file)]
invoking your script with quotes effectively results in:
[shell command (./script_name)][script argument ("<input_file")]
Sorry this is a few years late; hopefully someone will find this useful.
The simple script below does not work when, rather than passing a single file name, I want to pass multiple files through expansion characters like *
#!/bin/bash
fgrep -c '$$$$' $1
If I give the command script.sh file.in the script works. If I give the command script.sh *.in it doesn't.
Use "$#" to pass multiple file names to fgrep. $1 only passes the very first file name.
fgrep -c '$$$$' "$#"