Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Task 1:
If the Time is AM, print "It is Morning". If it is PM, print "It is not morning".
Task 2:
Given 2 arguments passed to the script.
Validate that 2 arguments have been submitted. If three arguments have not been provided, print "Must Supply 2 Arguments" and exit the script
Argument 1: Should be a directory (needs validated). If this does not exist, print "Directory: directory, does not exist" and exit the script
Argument 2: Should be a file (needs validated). If this does not exist, print "File: filename, does not exist" and exit the script.
If all arguments are valid, print "Given valid: filename and directory"
This is what I have so far
echo "James DuBois: 555555 - Task 1"
TIME=$(date "+%H")
if [ $TIME -lt 12 ]; then
echo "morning"
else
echo "not morning"
fi
echo "Task 2"
[ -d "$1" ] || exit
[ -d "$2" ] || exit
[ $# == 2 ] || exit
echo "arg1: $1"
echo "arg2: $2"
James, BASH is a wonderful, flexible shell. It has its warts, but if you need to do anything having to do with Linux system administration, etc.., you can do it in bash. Your tasks are to familiarize you with using conditional expressions (tests). There are tests for just about anything you need. That's why I pointed you to the CONDITIONAL EXPRESSIONS part of man bash.
Your second task requires the input of a filename so you can test it. I presume it is intended to be passed as an argument to your script (called positional parameters). Here is one way to approach the test. Note: I have interchanged output routines echo and printf intentionally for your benefit (printf being a bit more robust). Take a look at the following and let me know what questions you have:
#!/bin/bash
# My first script
#
# echo & printf are used at random below -- intentionally
#
[ -z $1 ] && { # validate at least 1 argument given on command line
printf "error: insufficient input. usage: %s filename\n" "${0##*/}"
exit 1
}
printf "\nJames DuBois: 5555555\n\n Task 1\n\n"
TIME=$(date "+%H")
## test for time of date: morning/not morning
if [ $TIME -lt 12 ]; then
printf " morning - time for coffee\n"
else
echo " not morning - time for scotch"
fi
echo -e "\n Task 2\n"
printf "Testing whether '%s' is a valid file.\n\n" "$1"
## test for file using compound commands
[ -f "$1" ] && echo -e " file found: '$1'\n" || printf " file not found: '%s'\n\n" "$1"
echo -e "Second test whether '$1' is a valid file.\n"
## test for file using if; then; else; fi
if [ -f "$1" ]; then
printf " file found: '%s'\n\n" "$1"
else
echo -e " file not found: '$1'\n"
fi
exit 0
Use/Output
$ bash ~/scr/tmp/stack/morningfile.sh
error: insufficient input. usage: morningfile.sh filename
$ bash ~/scr/tmp/stack/morningfile.sh mtrx_simple_dyn.c
James DuBois: 5555555
Task 1
not morning - time for scotch
Task 2
Testing whether 'mtrx_simple_dyn.c' is a valid file.
file found: 'mtrx_simple_dyn.c'
Second test whether 'mtrx_simple_dyn.c' is a valid file.
file found: 'mtrx_simple_dyn.c'
$ bash ~/scr/tmp/stack/morningfile.sh dog.c
James DuBois: 5555555
Task 1
not morning - time for scotch
Task 2
Testing whether 'dog.c' is a valid file.
file not found: 'dog.c'
Second test whether 'dog.c' is a valid file.
file not found: 'dog.c'
This will have some additional advantages while doing the same thing in task 2:
echo "Task 2"
[[ -d $1 && ! -L $1 && -f $2 && ! -L $2 ]] || exit
printf "%s\n" "arg1: $1" "arg2: $2"
It checks for symbolic links with the -L option.
[[ ]] has some advantages over [ ] like dealing with white spaces without the need for quoting variables.
If you want to print messages while checking for directory and file:
[[ ! -d $1 || -L $1 ]] && echo "Directory doesn't exist" && exit
[[ ! -f $2 || -L $2 ]] && echo "File doesn't exist" && exit
printf "%s\n" "arg1: $1" "arg2: $2"
Related
This question already has answers here:
An example of how to use getopts in bash
(8 answers)
Closed 7 months ago.
Can some please help how to pass named command line arguments to my shell script. Something like below.
./myOwnShellScript.sh -name Thor -tool Hammer
Below is one way to implement
#!/bin/bash
#################################################################################################
# Script name - myOwnShellScript.sh
# Description - This script is used to implement my own logic.
# Author - Tony
#################################################################################################
function usage(){
echo "Here is usage..."
echo "./myOwnShellScript.sh -name <<Name of your hero>> -tool <<your hero's tool>>"
}
function paramMap(){
declare -A params=( ["name"]="name" ["tool"]="tool" )
paramVarName="${params[${1}]}"
[ -z "${paramVarName}" ] && echo "info" || echo "${paramVarName}"
}
####################################################################################
#----------------------------------------------------------------------------------#
# Main starts, the script execution starts here. #
#----------------------------------------------------------------------------------#
####################################################################################
export TERM="xterm"
clear
trap "exit 1" TERM
export TOP_PID=$$
CURR_TIME=$(date +"%Y-%m-%d-%T")
echo -e "\n**********************************************"
echo -e "\n myOwnShellScript.sh Script Started ${CURR_TIME}"
echo -e "\n**********************************************"
##################################################################################################
# Variable Declaration
##################################################################################################
#Read command line parameters and set script variables.
while [ $# -gt 0 ]; do
if [[ $1 == *"-"* ]]; then
v="${1/-/}"
p=$(paramMap ${v})
paramValue=$([ -z "$2" ] && echo "1" || echo "$2")
declare $p="${paramValue}"
fi
shift
done
echo "Here is your hero ${name}"
echo "His tool is ${tool}"
This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
using OR in shell script
(2 answers)
Closed 7 months ago.
here is my simple script prova.sh:
#!/bin/bash
echo "\$# = [$#]"
echo "\$1 = [$1]"
if [ $# -ge 2 || $1="-h" ]
then
echo "#########################################################################"
echo -e "usage: $0 \t launches the program only"
echo -e " $0 -s\t shows the command fired and launches the program"
echo -e " $0 -so\t shows only the command fired"
echo -e " $0 -h\t shows this guide"
echo "#########################################################################"
exit 0
fi
command="ls -la"
if test "$1"="-so" || "$1"="-s"
then
echo "Fired command:"
echo $command
fi
if test "$1"!="-so"
then
$command
fi
here is the output:
$> ./prova.sh -h
$# = [1]
$1 = [-h]
./prova.sh: row 6 : [: "]" missing
./prova.sh: row6: -h=-h: command not found
Fired command:
ls -l
totale 4
-rwxrw-r--. 1 user user 632 20 lug 16.13 prova.sh
I expected just the help
you need to close every test using single brackets, the shell way, if [ $# -ge 2 ] || [ $1 = "-h" ]; then ... this will fix it. If you still use single brackets way, is safe to enclose you variables with double quotes, so if they are empty, you are safe, like this if [ "$#" -ge 2 ] || [ "$1" = "-h" ]; then ... or you can just put them inside a double bracket, and bash will handle this for you if [[ $# -ge 2 || $1 = "-h" ]]; then ...
I am trying to check if a user types multiple arguments in a command line using case and if/else statements. What's wrong is that I keep getting the default case instead of the same command, but with 2 more arguments. For instance, one of my conditions is:
del)
if [ -z "$2" ] || [ -z "$3" ]
then
echo "Usage: removes a file"
else
echo "using Bash command: rm $2 $3"
rm $2 $3
echo done
fi
prints the first condition, but if I type, say, del aaa bbb, I get the default case, which is:
echo "ERROR: Unrecognized command"
I'm also using this to read a user's input, if that helps.
read -p "wcl> " -r wcl $2 $3
I don't really know if there's a better way to solve this without scrapping all my code and starting from scratch.
This is the full code:
#!/bin/bash
#use read command
echo Welcome to the Windows Command Line simulator!
echo Enter your commands below
while true
do
read -p "wcl> " -r wcl $2 $3
case $wcl in
dir)
echo "using Bash command: ls $2 $3"
ls
continue
;;
copy)
FILE="$2"
if [ "$#" -ne 3 ]
then
echo "Usage: copy sourcefile destinationfile"
else
echo "using Bash command: cp $2 $3"
if [ -f "$FILE" ]
then
cp $2 $3
else
echo "cannot stat $FILE: No such file or directory">&2
fi
echo done
fi
continue
;;
del)
if [ -z "$2" ] || [ -z "$3" ]
then
echo "Usage: removes a file"
else
echo "using Bash command: rm $2 $3"
rm $2 $3
echo done
fi
continue
;;
move)
if [ -z "$2" ] || [ -z "$3" ]
then
echo "Usage: moves a file to another file name and location"
else
echo "using Bash command: mv $2 $3"
mv $2 $3
echo done
fi
continue
;;
rename)
if [ -z "$2" ] || [ -z "$3" ]
then
echo "Usage: renames a file"
else
echo "using Bash command: mv $2 $3"
mv $2 $3
echo done
fi
continue
;;
ipconfig)
ifconfig eth0 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1
continue
;;
exit)
echo "Goodbye"
exit 1
;;
^c)
echo "Goodbye"
exit 1
;;
*)
echo "ERROR: Unrecognized command"
continue
esac
done
You can't use read to set the positional parameters, although it isn't clear why you would need to here. Just use regular parameters.
while true
do
read -p "wcl> " -r wcl arg1 arg2
case $wcl in
dir)
echo "using Bash command: ls $arg1 $arg2"
ls "$arg1" "$arg2"
continue
;;
# ...
esac
done
The way read -r wcl $2 $3 is executed is that $2 and $3 are first expanded to give names that read will use to set variables. If those aren't set, then the command reduces to read -r wcl, and so your entire command line is assigned to the variable wcl, not just the command.
However, read by itself is not going to do the same parsing that the shell already does, if you goal is to write your own shell.
If you are really using bash, you can insert the words you read into positional parameters through an array. (You could also just leave them in the array, but the syntax for referring to positional parameters is simpler.)
# -a: read the successive words into an array
read -r -p "wcl> " -a params
# set the positional parameters to the expansion of the array
set -- "${params[#]}"
wcl=$1 # Or you could do the case on "$1"
This will also set $# to the number of words read, as a side-effect of setting the positional parameters.
As #chepner points outs, the read is problematic: It simply splits the input into whitespace-separated words, without respecting quotes, backslashes, and whatever other shell metacharacters you might want to implement. Doing a full bash-style parse of a command-line in bash itself would be quite a difficult exercise.
I am trying to write a simple program that checks if a given filename refers to a directory. But I keep getting an error saying that "bad interpreter: no such file or directory" when I run ./isdir.sh (This is the name of the script).
here is my code:
#!bin/sh
if [[ $# -ne 1 ]];then
echo "Usage: $0 dir"
exit 1
fi
dir="$1"
dirname = "$1"
if [[ ! -d "$dir" ]]; then
echo "Error: directory $dir not found."
exit 2
fi
if [[ -d "$dirname" ]]; then
echo "$dirname is a directory."
exit 3
ALSO, IMPORTANT QUESTION:
How do I handle input values that contain spaces in them?
You could do this:
#!/bin/bash
if [[ $# -ne 1 ]]; then
echo "Usage: $0 dir"
exit 2
fi
dir="$1"
rc=1
if [[ -d "$dir" ]]; then
# it is a directory
rc=0
elif [[ -e "$dir" ]]; then
echo "Error: '$dir' is not a directory"
else
echo "Error: directory '$dir' does not exist"
fi
exit "$rc"
Don't need the dirname variable.
The script is safe for directories that have white spaces or wild cards in their name as we have enclosed the variable in double quotes.
Exit code of 2 is a Unix standard for invalid argument error; exit 1 is all other errors. However, you can change the exit codes as per your need.
See this related post for more perspectives around this problem: Check if a directory exists in a shell script
This is a part of a script I'm trying to write.
If the directory exist there is no problem, but I don't know what to do if it not exists.
Some one has an idea how to solve this.
Thanks
do echo "$number"
newdir="../FILE-ID/*/${number:2:1}${number:1:1}/+33$number"
nbrdir=$(ls -lrtd $newdir|wc -l)
echo "$nbrdir"
if [ "$nbrdir" -gt 1 ]; then
echo "$number"
echo "error 1.greater"
fi
if [ "$nbrdir" -eq 1 ]; then
echo " equal 1"
else
echo "equal 0"
fi
done
You can use the following to test whether a file (including a directory) exists:
if [[ -f ${newdir} ]]; then ...
or another switch if you want to test specifically just for a directory:
if [[ -d ${newdir} ]]; then ...
A more comprehensive list can be found here.
If your directory name contains wildcards and matches potentially zero or more, you can use:
nbrdir=$(ls -1d ${newdir} 2>/dev/null | wc -l)
This should give you a count of matching directories. Note that any error message which might be generated will be directed to /dev/null which is probably what you want here to avoid errors messing up your output.
[ -d $newdir ] && echo "Directory exists" || echo "Directory does not exists"