Errors from if and else statements in shell

2019-07-24 06:44发布

I am just new to programming in Unix and have a small issue that I am unsure of how to solve. The objective of this piece of my script is to offer the user various options as to the type of scan they would like to use. This scan detects duplicate files with specified variables depending on the option chosen.

I am unable to get it working at all and am unsure why?

Also could you please offer me advice on how I could better display the selection screen if possible. I have only pasted part of my code as I would like to figure out the rest of my objective myself.

#!/bin/bash
same_name="1"
filesize="2"
md5sum="3"
different_name="4"
echo "The list of choices are, same_name=1, filesize=2, md5sum=3 and different name=4"
echo "Search for files with the:"
read choice 
if [$choice == "$same_name" ];then
find /home/user/OSN -type f -exec basename '{}' \; | sort > filelist.txt
find /home/user/OSN -type f -exec basename '{}' \; | sort | uniq -d > repeatlist.txt
else
ls -al /home/user/OSN  >2filelist.txt
fi

标签: bash shell
5条回答
ゆ 、 Hurt°
2楼-- · 2019-07-24 07:19

The shell command [ also known as test needs a space after it for the shell to parse correctly. For example:

if [ "x$choice" == x"$same_name" ] ; then

is equivalent to

if test "x$choice" == "x$same_name" ; then

prepending "x" to the variables is an idiom to prevent test from seeing too few arguments. Test would complain if called as test 5 == so if $choice and $same_name were empty the call to expr is syntactically correct.

You can also use the construct ${choice:-default} or ${choice:=default} to guard against unset or null shell variables.

查看更多
该账号已被封号
3楼-- · 2019-07-24 07:19

you can do it like this.

while true
do
cat <<EOF
The list of choices are:
  1) same name
  2) filesize
  3) md5sum
  4) different name
  5) exit
EOF
read -r -p "Enter your choice: " choice
case "$choice" in
 1)
    find /home/user/OSN -type f -exec basename '{}' \; | sort > filelist.txt
    find /home/user/OSN -type f -exec basename '{}' \; | sort | uniq -d > repeatlist.txt
 5) exit;
 *) ls -al /home/user/OSN  >2filelist.txt
esac
done
查看更多
男人必须洒脱
4楼-- · 2019-07-24 07:41

Bash's double square brackets are much more forgiving of quoting and null or unset variables.

if [[ $choice == "$same_name" ]]; then

You should take a look at Bash's select and case statements:

choices="same_name filesize md5sum different_name exit"

PS3="Make a selection: "    # this is the prompt that the select statement will display
select choice in $choices
do
    case $choice in
        same_name)
            find ...
            ;;
        filesize)
            do_something
            ;;
        .
        .
        .
        exit)
             break
             ;;
    esac
done
查看更多
看我几分像从前
5楼-- · 2019-07-24 07:42

It would help if you included the error messages you were receiving. When I tried this, I got an error of:

./foo: line 9: [1: command not found

This makes the problem fairly clear. The [ operator in the if statement is, in Unix's "never use something complicated when some simple hack will work" style, just another program. (See ls /bin/[ for proof!) As such, it needs to be treated like any other program with command-line options; you separate it from its options with whitespace. Otherwise, bash will think that "[$choice", concatenated, is the name of a program to execute and will try to execute it. Thus, that line needs to be:

if [ $choice == "$same_name" ];then

After I changed that, it worked.

Also, as a style suggestion, I'd note that the case construct is a much easier way to write this code than using if statements, when you've got more than one test. And, as noted in other answers, you should put " marks around $choice, to guard against the case where the user input is empty or contains spaces -- $choice, unquoted, will expand to a list of zero or more tokens separated by whitespace, whereas "$choice" always expands to a single token.

查看更多
等我变得足够好
6楼-- · 2019-07-24 07:46

can't believe nobody's picked up this error: if you use [ (or test), the operator for string equality is = not ==.

查看更多
登录 后发表回答