2013-05-03 2 views
2

Я использую Bash конкретно, но я думаю, что большинство снарядов ведут себя одинаково.Как работает && в оболочке?

Я часто

hg pull && hg update --clean 

Но это только мне пришло в голову, если hg pull возвращается 0 на успех, почему это выполнить команду hg up?

Как правило, работа оператора && заключается в том, что он выполнит только следующий аргумент, если предыдущий был правдивым. Является ли 0 правдой в Bash, что ли?

Это произошло, потому что я пытался делать эквивалент в Python, но я должен был написать это:

call(['hg','pull']) or call(['hg','update','--clean']) 
+1

0 считается успешным кодом возврата, потому что есть как правило, только один способ для успеха команды, но многие способы (соответствующие многим доступным ненулевым значениям) для комманды и потерпеть неудачу. В оболочке это помогает думать не с точки зрения «истинного» или «ложного», а с точки зрения «успеха» или «неудачи». – chepner

+0

Duplicate of [this previous question] (http://stackoverflow.com/questions/11714341/c-program-return-codes-and-bash-symbol) –

+0

@chepner: Я понимаю, почему 0 считается успешным, я просто не знаю 't понять, как '&&' "знает", что если он также может использоваться в контексте программирования, где 0 - false, а все остальное - true. – mpen

ответ

3

В помощь, вы можете вспомнить, чем команды, когда конец правильно (без ошибок) означают истинную. И его выход кода нулевого

так,

  • правильно = OK = верно = состояние выхода 0
  • некорректного = BAD = ложь = состояние выхода> 0

поэтому, например, правильный способ удаления всех файлов рекурсивно -

$ pwd 
/
$ cd /tnp && rm -rf * 
cd: can't change directory #and the rm WILL NOT executed 

и не

$ pwd 
/
$ cd /tnp ; rm -rf * 
cd: can't change directory #but the rm IS executed (in the root directory) 

Добавлено:

command1 && command2 && command3 
      ^  ^
       |   +-- run, only when command2 exited OK (zero) 
       | 
       +--run only when command1 exited OK (zero) 

Так, command3 не выполняется, если command1 или command2 не удалось. (когда comman1 терпит неудачу, команда 2 не будет выполнена (сбой), так что command3 тоже не будет выполнен.

Играть со следующим

run() { 
    echo "comand-$2($1)" 
    return $1 
} 

ok() { 
    run 0 $1 
} 
fail() { 
    run 1 $1 
} 

echo "OK && OK && ANY" 
ok A && ok B 0 && ok C 
echo 

echo "OK && FAIL && ANY" 
ok A 0 && fail B 1 && ok C 
echo 

echo "FAIL && ANY && ANY" 
fail A && ok B && ok C 
echo 

echo "OK || ANY || ANY" 
ok A || ok B || ok C 
echo 

echo "FAIL || OK || ANY" 
fail A || ok B || ok C 
echo 

echo "FAIL || FAIL || OK" 
fail A || fail B || ok C 
echo 

echo "FAIL && OK || OK" 
fail A && ok B || ok C 
echo 

Результат

OK && OK && ANY 
comand-A(0) 
comand-B(0) 
comand-C(0) 

OK && FAIL && ANY 
comand-A(0) 
comand-B(1) 

FAIL && ANY && ANY 
comand-A(1) 

OK || ANY || ANY 
comand-A(0) 

FAIL || OK || ANY 
comand-A(1) 
comand-B(0) 

FAIL || FAIL || OK 
comand-A(1) 
comand-B(1) 
comand-C(0) 

FAIL && OK || OK 
comand-A(1) 
comand-C(0) 

Последняя конструкция аккуратно, потому что вы можете написать

command1 && (commands if the command1 is successful) || (commands if not) 
+0

Как я писал в вопросе, я знаю, что он возвращает 0 на успех, но как работает цепочка с '&&'? – mpen

+0

Спасибо за обновление. Я думаю, что мое недоразумение состояло в том, что я знал, что 0 был * успешным * кодом возврата, но я полагал, что '&&' все равно будет относиться к нему как к ложному значению из-за того, как он используется на всех других языках. – mpen

2

Оператор «& &» работает в двух направлениях в Bash.

С одной стороны, это conditional operator как можно было ожидать:

if [ $condition1 ] && [ $condition2 ] 
# Same as: if [ $condition1 -a $condition2 ] 
# Returns true if both condition1 and condition2 hold true... 

if [[ $condition1 && $condition2 ]] # Also works. 
# Note that && operator not permitted inside brackets 
#+ of [ ... ] construct. 

С другой стороны, он может быть использован для конкатенации команд, в этом случае он явно проверяет коды возврата команд и происходит по цепочке, когда значение равно 0. See the doc.

+0

Ваш первый пример с '[...]' также является примером '&&', используемого для объединения двух команд. Это, строго говоря, не совпадает с '[... -a ...]', которая является единственной командой с несколькими аргументами, а не двумя отдельными командами, из которых вторая выполняется, если первая успешно завершается. – chepner

+0

Когда вы говорите, что она работает двумя способами, вы имеете в виду это в контексте '[...]' он оценивает '0' как фальшивость и все остальное как правдивое? – mpen

+0

, чтобы уточнить, что сказал чепнер в точности. Конструкция' [...] 'имеет код возврата: 0 по успеху (или« правдивый ») и 1 на сбой (или «ложь»), например, запуск '[-d foo]' сам по себе, а затем выполнение «echo $?», чтобы увидеть его код возврата, покажет вам, что 0 возвращается, когда каталог существует и возвращается 1 когда это не так. поэтому весь '[...]' обрабатывается так же, как и команда. –