Рассмотрим как более хитро управлять поведением скрипта.
Например, изучим давно нам уже привычный в других языках оператор условия if.
В bash тоже есть оператор сравнения. С одной стороны, он умеет делать всякие специфический проверки, например, определять тип файла или его наличие, а с другой стороны ведет себя очень хитро по сравнению с тем как это работает в привычных нам языках программирования.
Мы сначала рассмотрим старый синтаксис проверки bash команд, потому что его еще часто можно встретить, и чтобы у вас не возникало проблем в попытке его проинтерпретировать.
Оператор сравнение
В linux есть команда test
, она используется для сравнения значения аргументов. Синтаксис прост до безобразия:
так как это команда (ну или правильнее говорить, что это программа), то и при вызове надо выполнять требование к указанию аргументов. Например, если вы хотите сравнить два числа, то надо писать так
то есть тут три аргумента, первый – 3
, второй – это знак =
, ну и третий – 5
, обязательно через пробел.
попробуем ее вызвать:
хм, а где ж результат?
Тут дело в том, что результат функции определяется кодом возврата программы. Помните в C++ вы писали в конце main функции:
так вот этот 0 – и был кодом возврата вашей функции. В интерпретации bash, 0 – это успешный результат, и интерпретируется как ИСТИНА, если же программа возвращает что-то большое нуля – то считается что произошла ошибка, и это самое положительное число и есть номер ошибки.
Ну и что нам с того? А с того, что выполнив сейчас команду, да и в принципе выполнив любую команду, был возвращен какой-то код возврата.
Код возврата последней программы, хранится в специальной переменной $?
, как и всякую переменную ее значение можно вывести через echo
если мы видим положительное значение, значит результат работы программы ложь.
Давайте попробуем проверить что-нибудь точно истинное
О! получили 0, значит результат истина.
С помощью этой же программы можно проверить, например, существование файла
Возможно вам даже захочется узнать какое число больше, и вы попробуете написать вот так:
а потом
и удивитесь что получите один и тот же результат. А как так?
Дело в том что знак >
это зарезервированный символ в bash, помните мы с помощью него текст в файл загоняли. Так вот задача этого символа перенаправлять результат функции причем не код возврата, а именно выходной поток (который, например, получается через Console.WriteLine в C#) в файл.
Поэтому он интерпретирует ваше выражение как проверь пятерку или единичку на истинность, и если по пути захочешь чего-то написать, то запиши это в файл под именем 3
О как! А где же файл?
А вот и он:
пустой, между прочим.
Поэтому, если вы захотите сравнить два числа, то вам надо придется использовать следующие конструкции:
Так, ну ладно, к чему я собственно все это рассказываю. А к тому что оператор if в bash, проверяет не значение выражение, а код возврата программ, которое пишется после него.
Например, я могу создать файлик if_example.sh, написать в него такой скрипт
if test 3 -ge 1
then
echo "3 больше 1"
fi
сделать его исполняемым
и запустить
если же загнать какое-нибудь ложное выражение
if test 3 -ge 7
then
echo "3 больше 7"
fi
то ничего не выведется
Вроде все логично, но писать test весьма непривычно особенно если вы уже имеете опыт с каким-нибудь другим языком. И в linux в стародавние времена пошли на одну хитрость, они создали программу которую назвали [
и вызов этой программы эквивалентен вызову test.
И это дало возможность писать проверку условия как
и первое время так даже можно было писать. Что выглядело с одной стороны более похоже на нормальный язык. Но все-таки, одна открывающая скобка… В общем, со временем использование только открывающей скобки запретили и писать теперь надо
Кстати остатки этого наследия все еще обитают в системе. Например, в линуксе вы можете узнать расположение программы с помощью команды which
, вот так:
в этой папке /usr/bin лежит целая тьма всяких программ
там можно найти даже наш git. И там есть команда под именем [
А вообще, на самом деле, современный bash уже не использует ни программу test
ни программу [
, они встроенны в bash
и работают уже как часть языка bash.
Проверка нескольких условий
Иногда может захотеться проверить несколько условий, в этом случае у вас есть несколько вариантов. Первый вариант есть результат того что bash оперирует вызовами программ. А в линуксе можно запустить последовательно несколько команд вот так:
test 1 -lt 2 && test 2 -lt 5
в этом случае если test 1 -lt 2
вернет истину (то есть код возврата 0), то будет выполнена вторая команда, которая test 2 -lt 5
если же test 1 -lt 2
вернет ложь, то вторая команда выполняется не будет. Можно, например, даже так писать
то есть если 1 меньше 2 то выведи файлы в папке.
то есть в первом случае список файлов вывелся, а во втором уже нет. Потому что условие было ложно.
Ну и как есть оператор &&
(логическое И) так и есть оператор ||
(логическое ИЛИ), который работает в точности наоборот. Если первая программа вернула ложь, то выполняется вторая команда, а если вернулась истинна, то не выполняется.
Давайте проверим:
То есть в принципе такими однострочниками можно пользоваться как перключателями типа выполнить или не выполнить ту или иную программу.
Но понятно, что такое применимо только в очень простых случаях. А если мы хотим проверять сразу несколько условий в if. Как это написать?
Просто вспоминаем что после if пишется список команд для исполнения интерпретатором. Значит мы можем писать так
if test 1 -lt 2 && test 2 -lt 5
then
echo "Привет"
fi
А так как программе test соответствует программа [
, то можно переписать вот так
if [ 1 -lt 2 ] && [ 2 -lt 5 ]
then
echo "Привет"
fi
но это опять не очень привычно, теперь вот сразу две пары скобок писать надо. Поэтому современный bash поддерживает новый синтаксис проверки условий через двойные квадратные скобки
if [[ 1 -lt 2 && 2 -lt 5 ]]
then
echo "Привет"
fi
первое время конечно может пугать, но потом привыкаешь.
Управление поведением ssh-keygen
Вы можете передать в ssh-keygen дополнительные параметры. Например, путь к файлу с ключем, через флаг -f
ssh-keygen -t ed25519 -f "путь_к_файлу"
чтобы ssh-keygen
не просил passphrase
, надо указать флаг -N
с пустым параметром
ssh-keygen -t ed25519 -N ""
ну и чтобы функция не выводила никаких сообщений можно добавить флаг -q
(от слова quiet - тихо) без параметра.
Добавление текста в файла
Мы уже выше пробовали создавать файлы на лету через оператор перенаправлениz потока вывода >
.
Этот оператор всегда создает новый файл. Либо перезаписывается уже существующий. Ну типа
echo "Привет" > "new_file.txt"
если попробовать написать эту команду еще раз
echo "Пока" > "new_file.txt"
Так вот, есть способ сохранять содержимое файла, для этого надо вместо оператора >
использовать оператор >>
.
Двойной знак больше не перезаписывает файл, а добавляет текст к нему. Например
Вот таким не хитрым способом можно добавлять содержимое в уже существующий файл.