I have to write a command that rules with certain arguments.I need to show a message of usage of this command.I tried this:
if [ $1 = 'help' ]; then
echo Usage: '-a arguments at-author....'
fi
It doesn't work.Why?
case "$1" in
"help" )
echo "Usage ...." ;;
*) echo "others..." ;;
esac
Related
I wrote the following code :
echo "Choose between the following options:"
echo "1 - Create a new file"
echo "2 - Write in an existing file"
echo "3 - Change the path of a file"
echo "4 - Display a file"
echo "5 - Exit"
read number
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
do
echo "Enter a number between 1 and 5"
read number
done
if [ $number -eq 1 ]; then
echo "Enter a folder name"
read name
while [ -e $name ]
do
echo "The file name already exists enter a new name:"
read name
done
touch $name
fi
if [ $number -eq 2 ]; then
echo "Enter the folder name you want to edit :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
echo "Enter what you want to put in the file :"
read input
echo $input >> $name
fi
if [ $number -eq 3 ]; then
echo "Enter the folder name :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
if [ $number -eq 4 ]; then
echo "Enter the folder name you want to see :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
cat $name
fi
if [ $number -eq 5 ]; then
exit 0
fi
The code works just fine, but on the first condition :
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
I would like it to work to whatever number or string I put.
For example, if I put hello the program will crash.
Can someone tell me what should my first condition be?
Thank you for your help. And forgive me if my question is not in the rules of the forum (I just subscribed).
Your script says:
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
So, if $number is 1, it's not equal to 2. And if it's 2, it's not equal to 1. This will always evaluate as true, so you'll never exit the loop.
A variety of options exist that will be compatible with a numeric value and still gracefully handle non-numeric input. The following uses a basic regular expression to determine whether input is a digit from 1 to 5:
while read number && ! expr "$number" : '[1-5]$' >/dev/null; do
echo "Try again" >&2
done
You would probably be better off, though, using a case statement:
while read number; do
case "$number" in
1) function_1 ;;
2) function_2 ;;
... etc
*) echo "Invalid input, please try again." >&2; continue ;;
esac
break
done
The case statement is a more graceful way of expressing what might otherwise be achieved using if..elif..elif..fi:
while read number && ! expr "$number" : '[1-5]$' >/dev/null; do
echo "Try again" >&2
done
if [ "$number" = 1 ]; then
: do_something
elif [ "$number" = 2 ]; then
: do_something
elif [ "$number" = 3 ]; then
: do_something
elif [ "$number" = 4 ]; then
: do_something
elif [ "$number" = 5 ]; then
: do_something
else
echo "What am I doing?" >&2
fi
While this construct technically works, it's inelegant and harder to read. Much better to put your functionality into functions which get called from a case statement.
Note that it's always a good idea to quote your variables within a script like this. Do you know what happens with unquoted variables? If not, then quote your variables. :)
I would strongly suggest structuring your code with a case statement:
case $number in
1) code_for_1;;
2) code_for_2;;
...
*) echo "Invalid number" >&2;;
esac
If you wish to repeat (I would actually recommend taking the number as a command line argument instead of reading from stdin and aborting on an error), you could simply do:
while read number; do
case $number in
...
*) echo 'Invalid number' >&2; continue;;
esac
break
done
And write code_for_{1,2,3,4,5} as functions to factor out the logic. For example:
create_file() {
echo "Enter a file name"
while read name; do
if test -e "$name"; then
echo "The file $name already exists enter a new name" >&2
continue
fi
touch "$name"
break
done
}
while read number; do
case $number in
1) create_file;;
...
*) echo 'Invalid number' >&2; continue;;
esac
break
done
I have a UNIX script written in korn shell. I need to make it so that this statement:
while true
do
echo "What is the last name of the person you would like to modify:"
read last_name
if line=$(grep -i "^${last_name}:" "$2")
then
IFS=: read c1 c2 c3 c4 rest <<< "$line"
echo -e "Last Name: $c1\nFirst Name: $c2\nState: $c4"
while true
do
echo "What would you like to change the state to?:"
read state
if [[ $state -eq [A-Z] ]];then
echo "State: $state"
echo "This is a valid input"
break
else
echo "Not a valid input:"
fi
done
else
echo "ERROR: $last_name is not in database"
echo "Would you like to search again (y/n):"
read delete_choice
case $delete_choice in [Nn]) break;; esac
fi
done
;;
Specifically, I am having trouble with this code:
if [[ $state -eq [A-Z] ]];then
The point of this program is to modify a record in a text file but will only take the input of state abbreviations such as (MI, WA, KS, ....).
Try something like:
if echo $state | egrep -q '^[A-Z]{2}$'
then
...
fi
^[A-Z]{2}$ means your state starts and ends with CAPS alphabets of length two.
I am writing a script where I need to list files without displaying them. The below script list the files while executing which I don't want to do. Just want to check if there are files in directory then execute "executing case 2".
ls -lrt /a/b/c/
if [ $? != 0 ]
then
echo "executing case 2"
else
echo "date +%D' '%TNo files found to process" >> $LOG
Testing the return code of ls won't do you a lot of good, because it'll return zero in both cases where it could list the directory.
You could do so with grep though.
e.g.:
ls | grep .
echo $?
This will be 'true' if grep matched anything (files were present). And false if not.
So in your example:
ls | grep .
if [ $? -eq 0 ]
then
echo "Directory has contents"
else
echo "directory is empty"
fi
Although be cautious with doing this sort of thing - it looks like you're in danger of a busy-wait test, which can make sysadmins unhappy.
If you don't need to see the output of ls, you could just make it a condition:
[ "$(ls -lrt a/b/c)" ] && echo "Not Empty" || echo "Empty"
Or better yet
[ "$(ls -A a/b/c)" ] && echo "Not Empty" || echo "Empty"
Since you don't care about long output (l) or display order (rt).
In a script, you could use this in an if statement:
#!/bin/sh
if [ "$(ls -A a/b/c)" ]; then
echo "Not empty"
else
echo "Empty"
fi
I have the below script that is expected to work when the user invokes sh <scriptName> <propertyfile> It does work when I provide this at the dollar prompt. However, I am having two issues with the script.
If I provide just one argument, ie if I do - sh <scriptName>, I see the below error -
my-llt-utvsg$ sh temp.sh
Usage temp.sh
When I do -help, I see the below error -
my-llt-utvsg$ sh tmp.sh -help
-help does not exist
What am I doing wrong? Can someone please advise? I am a software developer that very rarely needs to do shell scripting, so please go easy on me ;)
#!/bin/bash
FILE="system.properties"
FILE=$1
if [ ! -f $FILE ];
then
echo "$FILE does not exist"
exit
fi
usage ()
{
echo "Usage $0 $FILE"
exit
}
if [ "$#" -ne 1 ]
then
usage
fi
if [ "$1" = "-help" ] ; then
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
exit
The reason your
if [ "$1" = "-help" ] ; then
check is not working is that it only checks $1 or the first argument.
Try instead:
for var in "$#"
do
if [ "$var" = "-help" ] ; then
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
fi
done
Which will loop over each argument and so will run if any of them are -help.
Try this as well:
#!/bin/bash
FILES=()
function show_help_info_and_exit {
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
exit
}
function show_usage_and_exit {
echo "Usage: $0 file"
exit
}
for __; do
if [[ $__ == -help ]]; then
show_help_info_and_exit
elif [[ -f $__ ]]; then
FILES+=("$__")
else
echo "Invalid argument or file does not exist: $__"
show_usage_and_exit
fi
done
if [[ ${#FILES[#]} -ne 1 ]]; then
echo "Invalid number of file arguments."
show_usage_and_exit
fi
echo "$FILES"
why in Cygwin Terminal - the if statement work
and ubuntu - unix - not working for
this code :
#!/bin/sh
valid_password="pass"
echo "Please enter the password:"
read password
if [ "$password" == "$valid_password" ]
then
echo "You have access!"
else
echo "Access denied!"
fi
#emil pointed the answer:
if [ "$password" = "$valid_password" ]
instead of
if [ "$password" == "$valid_password" ]
Also: did you give the script executing permissions? Try
chmod +x script_name
because the correct syntax to [ is:
[ a = b ]
From your error message it sounds like you wrote:
if ["$password" = "$valid_password" ]
change this to:
if [ "$password" = "$valid_password" ]
notice the space after [. if just takes a shell command, try to run it and depending if the exit code from the program is 0 it will run the commands inside the if statement.
In your terminal, write i.e.:
user#localhost$ true; echo $?
0
to test your if statement:
user#localhost$ pass=pass; valid=pass
user#localhost$ if [ "$pass" = "$valid" ]; then echo 'You have access!'; fi
As #nullrevolution said, the ! is evaluated if you use double quotes, it will try to run last command in your shell history, in this case that is matching u.
user#localhost$ uname
Linux
user#localhost$ !u
uname
Linux
user#localhost$ echo "!"
sh: !: event not found
This is because the ! is evaluated before the double quotes are matched, and echo is run. If you still want to use double quotes, you will have to escape the ! outside the quotes:
echo "Access denied"\!
#nullrevolution also said you could try with bash, which has a builtin syntax for the expression inside if statements.
#!/bin/bash
valid_password=pass
echo "Please enter the password:"
read password
if [[ "$password" == "$valid_password" ]]; then
echo 'You have access!'
else
echo 'Access denied!'
fi
Also in your program I guess you do not want to echo the password in the terminal, to turn off echo temporary change:
read password
to
stty -echo
read password
stty echo
if you forgot to write stty echo to turn on echo again, just write reset in your terminal, and it will reset the terminal to default settings.
A useful tutorial for bourn shell script can be found here:
http://www.grymoire.com/Unix/Sh.html