Ошибки из операторов if и else в оболочке - PullRequest
1 голос
/ 09 марта 2010

Я новичок в программировании на Unix и у меня есть небольшая проблема, которую я не знаю, как решить. Цель этого фрагмента моего сценария - предложить пользователю различные варианты типа сканирования, которое он хотел бы использовать. Эта проверка обнаруживает дубликаты файлов с указанными переменными в зависимости от выбранной опции.

Я вообще не могу заставить его работать и не знаю почему?

Также не могли бы вы дать мне совет, как мне лучше отобразить экран выбора, если это возможно. Я вставил только часть своего кода, поскольку сам хотел бы выяснить остальную часть своей цели.

#!/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

Ответы [ 5 ]

5 голосов
/ 09 марта 2010

Команде оболочки [, также известной как test, необходим пробел после нее, чтобы оболочка правильно проанализировала. Например:

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

эквивалентно

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

добавление "x" к переменным является идиомой, чтобы test не видел слишком мало аргументов. Test будет жаловаться, если вызывается как test 5 ==, поэтому, если $choice и $same_name пустые, вызов expr синтаксически правильный.

Вы также можете использовать конструкцию ${choice:-default} или ${choice:=default} для защиты от неустановленных или нулевых переменных оболочки.

3 голосов
/ 09 марта 2010

Будет полезно, если вы включите полученные сообщения об ошибках. Когда я попробовал это, я получил ошибку:

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

Это делает проблему довольно ясной. Оператор [ в операторе if заключается в том, что в Unix стиль «никогда не используйте что-то сложное, когда какой-то простой взлом будет работать» - это просто другая программа. (См. ls /bin/[ для доказательства!) Как таковой, он должен рассматриваться как любая другая программа с параметрами командной строки; Вы отделяете это от его вариантов с пробелами. В противном случае bash будет считать, что «[$ choice», объединенный, является именем программы для выполнения, и попытается выполнить ее. Таким образом, эта строка должна быть:

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

После того, как я это изменил, все заработало.

Кроме того, в качестве рекомендации по стилю я хотел бы отметить, что конструкция case является гораздо более простым способом написания этого кода, чем использование операторов if, когда у вас более одного теста. И, как отмечено в других ответах, вы должны поставить " отметки вокруг $choice, чтобы защититься от случая, когда пользовательский ввод пуст или содержит пробелы - $choice без кавычек расширится до нуля или списка больше токенов разделено пробелами, тогда как "$choice" всегда расширяется до одного токена.

1 голос
/ 10 марта 2010

вы можете сделать это так.

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
1 голос
/ 09 марта 2010

не могу поверить, что никто не подхватил эту ошибку: если вы используете [ (или test), оператор равенства строк будет =, а не ==.

1 голос
/ 09 марта 2010

Двойные квадратные скобки Bash гораздо более щадящие кавычки и нулевые или неустановленные переменные.

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

Вам следует взглянуть на операторы Баша select и case:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...