LINUX.ORG.RU

bash. запутался с условиями %)


0

1

всем привет.

есть такой код: «[ ! -d ~/c ] && mkdir ~/c && cd ~/c && echo ok || echo err»

вот как я понимаю его работу пошагово: проверяем, не существует ли еще каталога «~/c». если истина - создаем. если создать не удалось - выводим «err», если удалось - переходим в него и выводим «ok».

вопросы:

1. есть ли смысл в условии использовать двойные квадратные скобки?

2. последовательность операций разделенных «&&» выполняется до тех пор, пока каждая предыдущая завершается успехом? (вроде как да. но хочу утвердится.)

3. если же какая-то из операций завершилась с ошибкой - выполняется операция разделенная при помощи «||». вопрос: тут, после «||» я снова могу перечислять операции при помощи «&&» и «||» ? вопрос в том, каким образом обычно записывается такое перечисление чтоб не путаться в нем?

благодарен.

★★★

Последнее исправление: niXman (всего исправлений: 2)

Вы уже с трудом разбираетесь в написанном, а хотите превратить код в ещё больший mindfuck. Зачем?

aidaho ★★★★★
()

1. [ - внешняя программа test. [[ - bash builtin, будет некоторый прирост производительности

2. да, всё так - выполнять, пока все предыдущие успешно завершались

3. да. Выполняется группа, разделённая &&, если где-то ненулевой код возврата - выполнение группы прекращается и начинается выполнение следующей группы, которая после ||.

tiandrey ★★★★★
()
Ответ на: комментарий от tiandrey

по первому: скажите, имеет ли смысл вообще всегда использовать двойные квадратные скобки?

по остальному понятно.

niXman ★★★
() автор топика
Ответ на: комментарий от niXman

Дело вкуса. Вообще нужно сравнить man bash#CONDITIONAL EXPRESSIONS и man test, возможно, они несколько различаются.

Вот выдержка из bash faq:

E1) Why is the bash builtin `test' slightly different from /bin/test?

The specific example used here is [ ! x -o x ], which is false.

Bash's builtin `test' implements the Posix.2 spec, which can be
summarized as follows (the wording is due to David Korn):
   
Here is the set of rules for processing test arguments.
  
    0 Args: False
    1 Arg:  True iff argument is not null.
    2 Args: If first arg is !, True iff second argument is null.
	    If first argument is unary, then true if unary test is true
	    Otherwise error.
    3 Args: If second argument is a binary operator, do binary test of $1 $3
	    If first argument is !, negate two argument test of $2 $3
	    If first argument is `(' and third argument is `)', do the
	    one-argument test of the second argument.
	    Otherwise error.
    4 Args: If first argument is !, negate three argument test of $2 $3 $4.
	    Otherwise unspecified
    5 or more Args: unspecified.  (Historical shells would use their
    current algorithm).
   
The operators -a and -o are considered binary operators for the purpose
of the 3 Arg case.
   
As you can see, the test becomes (not (x or x)), which is false.

tiandrey ★★★★★
()
Ответ на: комментарий от tiandrey

И, кстати, я нагнал - если явно не указывать путь, то [ и test вызываются как builtin, а не как внешние программы.

tiandrey ★★★★★
()
Ответ на: комментарий от tiandrey

понял. спасибо. вопрос закрыт.

niXman ★★★
() автор топика

if ... fi могут быть читабельнее в таких случаях

anonymous
()
Ответ на: комментарий от tiandrey

Они не замещаются

внезапно:

$ which [
/usr/bin/[

примеры

например:

$ as='a s'; df='a s'
$ [ $as == $df ] && echo 1
bash: [: too many arguments
$ [[ $as == $df ]] && echo 1
1

anonymous
()
Ответ на: комментарий от anonymous

внезапно:

$ which [
/usr/bin/[

ну и что? если вы не будете писать

/usr/bin/[ xxx ]
то у вас будут кошерные встроенные фичи.

drBatty ★★
()
Ответ на: комментарий от anonymous

внезапно:

Для того, чтобы узнать, что же используется - builtin или вшнешняя программа, используется type:

$ type [
[ is a shell builtin

А which говорит только, где расположена внешняя программа.

tiandrey ★★★★★
()
Ответ на: комментарий от drBatty

и то кошернее

Чем же? И то, и то проверит, есть ли директория, перед созданием.

tiandrey ★★★★★
()
Ответ на: комментарий от drBatty

А чем именно кошернее? Вроде posix-овый ключ. И ввели его уже достаточно давно.

PS: Иногда я не совсем понимаю термин «кошернее», применяемый к некоторым фичам шеллов и ЯП.

OldFatMan
()
Ответ на: комментарий от anonymous

С какой стороны посмотреть. По мне, так builtin не заменяется внешним -_^

tiandrey ★★★★★
()
Ответ на: комментарий от OldFatMan

PS: Иногда я не совсем понимаю термин «кошернее», применяемый к некоторым фичам шеллов и ЯП.

Надо добавить, что на самом деле кашрут может касаться не только пищи. Помимо того, что уважаемый раввин может счесть кошерным или некошерным практически любой предложенный предмет или явление, есть еще и другие независимые правила ритуальной чистоты. Например, касательно тканей. В одежде иудей не может смешивать ткани растительного и животного происхождения — так, какой-нибудь шерстяной пиджак на льняной подкладке — некошерен.

(C)Уютное.

Если серьёзно, то bash настолько тормозной язык, что удваивать там количество операций просто глупо.

drBatty ★★
()
Ответ на: комментарий от drBatty

Насчёт кошерности не знал, по невежеству думал, что только к еде относится. Спасибо за «справочку».

Но в применении к шеллам и ЯП всё равно как-то мой «моск» со скрипом такой термин воспринимает. Ну привык я к более определённым характеристикам. ;)

Если серьёзно, то bash настолько тормозной язык, что удваивать там количество операций просто глупо.

Вот про это всегда и помню. Соответственно, и действую. :)

OldFatMan
()
Ответ на: комментарий от OldFatMan

Но в применении к шеллам и ЯП всё равно как-то мой «моск» со скрипом такой термин воспринимает. Ну привык я к более определённым характеристикам. ;)

мне кажется, что в Linux есть некоторые вещи, о которых ни в каких книгах не написано, и ни какой гуру не скажет. Их понимаешь исключительно с опытом. Некие «неписанные правила». Ну например, не нужно вставлять отрицание туда, где можно обойтись и без него, как в этом случае. Не, bash конечно будет работать... Но дольше. Но и не это главное - в таком жутком и ужасном одностроке, аффтор перестанет понимать его начало, ещё даже до написания его конца. А такие одностроки проще выбросить, и написать это велосипед с нуля. Лично мне жаль своего времени и сил. Да и неправильно это как-то... ИМХО.

Вот про это всегда и помню. Соответственно, и действую. :)

к счастью, в 95% случаев это не играет никакой практической роли. :)

drBatty ★★
()

3. если же какая-то из операций завершилась с ошибкой - выполняется операция разделенная при помощи «||». вопрос: тут, после «||» я снова могу перечислять операции при помощи «&&» и «||» ?

конечно. Только никому не рассказывайте.

вопрос в том, каким образом обычно записывается такое перечисление чтоб не путаться в нем?

if mkdir --parents "$DIR_NAME"; then
  # каталог создался
  cd "$DIR_NAME"
else
  err=$?
  echo "Случилось страшное!!!!111, с кодом $err."
  exit $err
fi

освойте 15 нерусских слов, и вы сможете понять, как это работает.

drBatty ★★
()
Ответ на: комментарий от drBatty

в Linux есть некоторые вещи, о которых ни в каких книгах не написано, и ни какой гуру не скажет. Их понимаешь исключительно с опытом.

Что есть, то есть. Много до чего доходишь исключительно экспериментальным путём.

Ну например, не нужно вставлять отрицание туда, где можно обойтись и без него, как в этом случае.

О_О

Это же аз и буки, основы кодирования на любом уровне. В любом учебнике это написано. Имхо, неудачный пример. В bash есть более укромные «тайнички». :)

А такие одностроки проще выбросить, и написать это велосипед с нуля.

Так может ТС сам этот однострок и написал. А если нет, то следовало бы ему самому попробовать. Самое лучшее обучение - решение практических задач с нарастающей сложностью.

к счастью, в 95% случаев это не играет никакой практической роли. :)

Ну, не скажи. С 50% случаев я ещё соглашусь. Но на bash достаточно легко наваять такой скрипт, который будет тормозить даже современные железки. Вот тут и начинается оптимизация. Во всяком случае, я так поступаю.

OldFatMan
()
Ответ на: комментарий от drBatty

А вот объясни ты мне, какой смысл в этой конструкции:

if mkdir --parents "$DIR_NAME";

а?

OldFatMan
()
Ответ на: комментарий от drBatty

Это я к тому, что:

-p, --parents
              Создает недостающие родительские каталоги для каждого
              указанного каталога.  Права  доступа  к  родительским
              каталогам  устанавливаются  в  значение  umask,  логически    
              сложенное с ‘u+wx’.  Аргументы, соответствующие
              существующим каталогам, игнорируются.  (Таким образом, если 
              каталог /a существует,  то  ‘mkdir  /a’  выдаст
              ошибку, а ‘mkdir -p /a’ — нет.)

Т.е., зачем писать кучу ненужного кода, если достаточно:

mkdir --parents "$DIR_NAME"; cd "$DIR_NAME"

Опять же, к вопросу об оптимизации. :)

OldFatMan
()
Ответ на: комментарий от OldFatMan

Что есть, то есть. Много до чего доходишь исключительно экспериментальным путём.

Только обрати внимание - никуда ты не дойдёшь только экспериментальным путём. Но вот если читать умеешь - то все проблемы решаемы.

Это же аз и буки, основы кодирования на любом уровне. В любом учебнике это написано. Имхо, неудачный пример. В bash есть более укромные «тайнички». :)

ну что есть в первом посте - то и есть.

Так может ТС сам этот однострок и написал. А если нет, то следовало бы ему самому попробовать. Самое лучшее обучение - решение практических задач с нарастающей сложностью.

угу. Вот только если решить построить дом, то плохая идея построить одноэтажный, потом достроить второй этаж, и т.д. - рухнет. Есть смысл почитать литературу, вырать котлован, залить надёжный фундамент, и уже возводить здание. А не пирамидки, как дети делают...

Ну, не скажи. С 50% случаев я ещё соглашусь. Но на bash достаточно легко наваять такой скрипт, который будет тормозить даже современные железки. Вот тут и начинается оптимизация. Во всяком случае, я так поступаю.

Ну лично я использую bash исключительно как связующее. Если мне нужна БД, я возьму БД, а если мне нужен архиватор, я возьму архиватор. Хотя _могу_ и на bash'е. Но не буду. Потому у меня на долю баша мало нагрузки приходится.

А вот объясни ты мне, какой смысл в этой конструкции:

if mkdir --parents "$DIR_NAME";

а?

А это называется, «что вижу - то пою»: Если каталог создался, то в него переходим, иначе завершаем работу (ну или там я не знаю что).

Лично я вообще часто не вижу никакой необходимости плодить лишние сущности - при работе скрипта команда может дать два результата: смогла/несмогла. Всё. Если не смогла - это уже совсем другая история, и требует разбирательства. Потому логично не парится с проверками во время работы, а просто засунуть команду в if.

Благо bash это позволяет. А костыли ||&& тут не к чему. Они в этом смысле нелогичные, и значит плохо поддерживаются. Мне такого щастья не нужно.

Как всегда - всё ИМХО.

drBatty ★★
()
Ответ на: комментарий от OldFatMan

Т.е., зачем писать кучу ненужного кода, если достаточно:

А если не сможет? Что тогда? Между прочим, command1 && command2 ситуацию спасает.

Опять же, к вопросу об оптимизации. :)

надёжность куда важнее.

drBatty ★★
()
Ответ на: комментарий от drBatty

Извини, ступил. Сначала понаписюкал аж в 2х частях, потом стал думать. А надо было наоборот. :)

Зациклился на существовании/несуществовании каталога. Забыл, что могут быть ошибки типа: «нет места на диске», «нет прав для создания каталога», «ноды кончились» и т.д.

Да, в данном случае «оптимизация» была совершенно ни при чём.

В общем, полностью признаю свою ошибку.

OldFatMan
()
Ответ на: комментарий от OldFatMan

В общем, полностью признаю свою ошибку.

это и не ошибка. Ошибка - использовать не тот инструмент. Я сам ведь только-что написал

if [ ! -d "$TRANS_DIR" ]; then
	mkdir --parent "$TRANS_DIR" || exit 112
	chmod 1777 "$TRANS_DIR" || exit 113
fi

но тут мне нужно сделать два действия, создать каталог, и выставить на него права. Причём только если его нет. Если есть - права трогать нельзя. Потому мне и пришлось сделать именно так, ибо других вариантов я не вижу, за исключением субшелла, но это ещё менее «кошернее» :)

Нам ТС так и не поведал, чего ему собственно надо, потому спорить тут бесполезно..

drBatty ★★
()
Ответ на: комментарий от r2d2

а в случае [[ это не было ошибкой, что я и показал

anonymous
()
Ответ на: комментарий от drBatty

Нам ТС так и не поведал, чего ему собственно надо

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

нет, конечно, я сильно лучше знаю пайтон, и предпочитаю решать скриптовые(и не только) задачи с его помощью. но, как я уже говорил ранее, на данном этапе меня интересует bash.

всем благодарен.

niXman ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.