Checking for the correct number of arguments - shell

How do i check for the correct number of arguments (one argument). If somebody tries to invoke the script without passing in the correct number of arguments, and checking to make sure the command line argument actually exists and is a directory.

#!/bin/sh
if [ "$#" -ne 1 ] || ! [ -d "$1" ]; then
echo "Usage: $0 DIRECTORY" >&2
exit 1
fi
Translation: If number of arguments is not (numerically) equal to 1 or the first argument is not a directory, output usage to stderr and exit with a failure status code.
More friendly error reporting:
#!/bin/sh
if [ "$#" -ne 1 ]; then
echo "Usage: $0 DIRECTORY" >&2
exit 1
fi
if ! [ -e "$1" ]; then
echo "$1 not found" >&2
exit 1
fi
if ! [ -d "$1" ]; then
echo "$1 not a directory" >&2
exit 1
fi

cat script.sh
var1=$1
var2=$2
if [ "$#" -eq 2 ]
then
if [ -d $var1 ]
then
echo directory ${var1} exist
else
echo Directory ${var1} Does not exists
fi
if [ -d $var2 ]
then
echo directory ${var2} exist
else
echo Directory ${var2} Does not exists
fi
else
echo "Arguments are not equals to 2"
exit 1
fi
execute it like below -
./script.sh directory1 directory2
Output will be like -
directory1 exit
directory2 Does not exists

You can check the total number of arguments which are passed in command line with "$#"
Say for Example my shell script name is hello.sh
sh hello.sh hello-world
# I am passing hello-world as argument in command line which will b considered as 1 argument
if [ $# -eq 1 ]
then
echo $1
else
echo "invalid argument please pass only one argument "
fi
Output will be hello-world

Related

Bash mkdir and cd script returning error but still working

For a while, I've had a need for a bash script to make a directory and cd into it. Most of the solutions online work but are very minimal so I wanted to make one that handles things like creating parent directories and permission checking. Here's my code:
#!/bin/bash
function mkcd() {
# Check for no arguments
if "$#" -eq 0; then
echo "Error: no arguments provided"
return 1
fi
# Checks if help flag is used
# Not with other flags to ensure the directory isn't assumed to be a flag
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
echo "mkcd - Makes a directory and changes directory to it\n"
echo "Flags:"
echo " -h, --help Display help message"
echo " -p, --parents Makes parent directories as neeeded"
echo " -a, --absolute Receive an absolute directory instead of relative\n"
echo "Format: mkcd [arguments] directory"
return 0
fi
# Flag checker
while test "$#" -gt 1; do
case "$1" in
-p | --parents)
mkcd_parents=true
shift
;;
-a | --absolute)
shift
;;
esac
done
mkcd_path="$1"
if [[ ! -w "$PWD" ]]; then
echo "Error: Permission denied"
return 1
fi
if [[ -d "$mkcd_path" ]]; then
echo "Error: Directory already exists"
return 1
fi
if "$mkcd_parents"; then
mkdir -p "$mkcd_path"
cd "$mkcd_path"
else
mkdir "$mkcd_path"
cd "$mkcd_path"
fi
}
I also sourced it in my .zshrc file with source ~/bin/*
When I run the command, I get this output:
~ ❯ mkcd test_dir
mkcd:3: command not found: 1
mkcd:45: permission denied:
~/test_dir ❯
Does anyone understand why I'm getting this error?
if "$#" -eq 0; then
Since you have one argument to the script, that becomes after expansions
if 1 -eq 0; then
You probably meant to do
if [[ "$#" -eq 0 ]]; then
instead. (With either of [ .. ] or [[ .. ]].)
As an aside, I would change this
if "$mkcd_parents"; then
to
if [ "$mkcd_parents" = "true" ]; then
Otherwise if the -p option isn't given, $mkcd_parents is unset, "$mkcd_parents" expands to the empty string, and you get an error about that command not being found.

Semaphore thinks lock file already exists

I'm using link to create a semaphore - the idea is to lock out of writing to a db.
Here I have a script to create a table in a database:
#!/bin/bash
if [ "$#" -lt 3 ]; then
echo "Not enough parameters"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Too many parameters"
exit 1
fi
if [ ! -d "$1" ]; then
echo "That database doesn't exist!"
exit 1
fi
./P.sh $1
if [ -f "$1/$2.txt" ]; then
echo "That table already exists!"
./V.sh $1
exit 1
else
touch "$1/$2.txt"
fi
./V.sh $1
echo "$3" > "$1/$2.txt"
echo "Ok, table created"
exit 0
Here's my P file:
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage $0 mutex-name"
exit 1
elif [ ! -e "$1" ]; then
echo "Target for the lock must exist"
exit 2
else
while ! ln "$1" "$1.lock"; do
sleep 1
done
exit 0
fi
and my V:
#! /bin/bash
if [ -z "$1" ]; then
echo "Usage $1 mutex-name"
exit 1
else
rm "$1.lock"
exit 0
fi
let's say I create a table by running ./create_table people footballers age,height
This should create a file footballers.lock (created by P) and then once the writing has happened the V should remove it. But for some reason the P thinks that the .lock file already exists, and it definitely doesn't.
Can anyone spot what's going wrong?
Found it - you can't use ln on directories...

Testing presence of multiple files within loop

Assume a bash script to which four commandline arguments are passed. Each of these arguments represents a path to, and a name of, an input file (i.e., INF1, INF2, INF3, INF4). I would like to evaluate for each of these four input files, if it exists and - if a file does not exist as specified - exit the script.
#!/bin/bash
# Assigning commandline arguments
INF1=$1
INF2=$2
INF3=$3
INF4=$4
# Check if input files exist
if [ ! -f $1 ]; then
echo -ne " ERROR | File not found: $1\n"
exit 1
fi
if [ ! -f $2 ]; then
echo -ne " ERROR | File not found: $2\n"
exit 1
fi
if [ ! -f $3 ]; then
echo -ne " ERROR | File not found: $3\n"
exit 1
fi
if [ ! -f $4 ]; then
echo -ne " ERROR | File not found: $4\n"
exit 1
fi
I would think that having four individual if-statements here is unnecessary, and that the same functionality can be achieved with a single if-statement, wrapped into a loop. How can I reduce the code in this aspect?
in a script
#!/bin/bash
for v; do
if [ ! -f "$v" ]; then
echo "ERROR | File not found: $v"
exit 1
fi
done
You can declare an array and assing the variables and loop through it.
ARRAY=()
ARRAY+=$1
ARRAY+=$2 ..
and
for i in "${arrayName[#]}"
do
:
# do whatever on $i
done

sed command in Solaris server

I have many javascript files in my solaris server which have some debug, print and trace statements which I want to comment. There are hundreds of file like this.
I have found a script to do this but the problem is the script is removing the urhk_b2k_printRepos statement instead of commenting it. The script is as below:
if [ $# -ne 2 ]
then
echo "usage: prdel <script file name> <directory in which scripts are present>"
exit 1
fi
file=$1
dir=$2
if [ ! -s ${file} ]
then
echo "script file ${file} either does not exist or is empty (zero bytes)"
echo "Exiting..."
exit 1
fi
if [ ! -d ${dir} ]
then
echo "Invalid directory ${dir} entered"
echo "Exiting..."
exit 1
fi
cordir="./corrected"
prlogdir="./prlog"
if [ -d ${cordir} ]
then
echo "The corrected directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${cordir}
fi
if [ -d ${prlogdir} ]
then
echo "The prlog directory exist in the path, Please remove and run the tool again"
echo "Exiting..."
exit 1
else
mkdir ${prlogdir}
fi
errFile="$prlogdir/scr_err.rpt"
sucFile="$prlogdir/scr_suc.rpt"
Lines=`wc -l $file`
cntr=1
while [ $cntr -le $Lines ]
do
src=`head -$cntr $file|tail -1`
echo "$cntr. Processing $src...."
srcPath="${dir}/${src}"
if [ ! -s ${srcPath} ]
then
echo "Script file ${src} does not exist in the path given" >> ${errFile}
else
cp $srcPath $cordir/$src.tmp
srctemp="$cordir/$src.tmp"
srccor="$cordir/$src.corrected"
printcnt=`grep -ci "^[ ]*print" $srctemp`
if [ $printcnt -ne 0 ]
then
cat $srctemp|sed 's/^[ ]*[ ]*print[ ]*(/#print(/'|sed 's/^[ ]*[ ]*PRINT[ ]*(/#PRINT(/' > $srccor
mv $srccor $srctemp
fi
prreposcnt=`grep -ci "printrepos" $srctemp`
if [ $prreposcnt -ne 0 ]
then
cat $srctemp|sed 's/^.*urhk_b2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_PrintRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_B2k_printRepos.*/#Printrepos statement removed/'|sed 's/^.*urhk_b2k_PrintRepos.*/#Printrepos statement removed/' > $srccor
else
cp $srctemp $srccor
fi
echo "Script file $src correction is done" >> ${sucFile}
rm $srctemp
diff $srcPath $srccor >> $prlogdir/$src.diff.rpt
fi
cntr=`expr $cntr + 1`
done
echo "done"
I am completely new to shell scripting. Can anyone help me to modify this script to comment "urhk_b2k_printRepos" lines and also comment "TRACE ON" lines.

How to count and check passed arguments?

How can I translate the following Ruby code to Bash?
if ARGV.length == 0
abort "\nError: The project name is required. Aborting...\n\n"
elsif ARGV.length > 2
abort "\nError: The program takes two arguments maximum. Aborting...\n\n"
end
#!/bin/bash
USAGE="$0: <project name> [subproject attribute]"
if [ $# -lt 1 ]; then echo -e "Error: The project name is required.\n$USAGE" >&2; exit 1; fi
if [ $# -gt 2 ]; then echo -e "Error: Two arguments maximum.\n$USAGE" >&2; exit 1; fi
The following should be what you need:
#!/bin/bash
if [ $# -eq 0 ]; then
echo -e "\nError: The project name is required. Aborting...\n\n"
exit 1
elif [ $# -gt 2 ]; then
echo -e "\nError: The program takes two arguments maximum. Aborting...\n\n"
exit 1
fi
The TLDP bash guide is very good if you are looking to learn bash, see TDLP Bash guide.
Maybe:
#!/bin/bash
function functionName {
if [ $# = 0 ]
then echo "\nError: The project name is required. Aborting...\n\n"; exit 1
fi
if [ $# \> 2 ]
then echo "\nError: The program takes two arguments maximum. Aborting...\n\n"; exit 1
fi
}
functionName a

Resources