Bash если файл содержит
Каким бы простым ни был графический интерфейс в Linux и сколько бы там ни было функций, все равно есть задачи, которые удобнее решать через терминал. Во-первых, потому что это быстрее, во-вторых - не на всех машинах есть графический интерфейс, например, на серверах все действия выполняются через терминал, в целях экономии вычислительных ресурсов.
Если вы уже более опытный пользователь, то, наверное, часто выполняете различные задачи через терминал. Часто встречаются задачи, для которых нужно выполнять несколько команд по очереди, например, для обновления системы необходимо сначала выполнить обновление репозиториев, а уже затем скачать новые версии пакетов. Это только пример и таких действий очень много, даже взять резервное копирование и загрузку скопированных файлов на удаленный сервер. Поэтому, чтобы не набирать одни и те же команды несколько раз можно использовать скрипты. В этой статье мы рассмотрим написание скриптов на Bash, рассмотрим основные операторы, а также то как они работают, так сказать, bash скрипты с нуля.
Выводы
В статье была рассмотрена проверка существования файла bash, а также его пустоты. Обе функции дополняют друг друга, поэтому использовать их в связке - эффективный приём.
Хороший тон в написании сценариев командного интерпретатора - сначала определить тип файла и его дальнейшую роль в программе, а затем уже проверять объект на существование.
Bash (Bourne Again Shell) — это командная оболочка, использующаяся в таких UNIX-системах, как Linux или MacOS. Она позволяет управлять компонентами ОС с помощью определённых запросов, которые вводятся в консоль или берутся из скрипта.
Как новичкам, так и опытным пользователям будет полезно узнать или вспомнить основные команды Bash для управления такими важными аспектами системы, как файлы и каталоги. Этот вопрос будет разобран на примере ОС Linux.
Выводы
В представленных операциях сравнения строк Bash есть определённые нюансы, которые стоит понять для предотвращения ошибок работы сценариев. Но таких ситуаций на практике встречает много, поэтому запомнить все (и тем более, описать) не получится.
При сравнении строк в виде переменных их можно заключать в кавычки практически всегда, так как это считается правилом хорошего тона, а заодно и страхует от семантических ошибок.
В операционных системах GNU/Linux любые объекты системы являются файлами. И проверка существования файла bash - наиболее мощный и широко применяемый инструмент для определения и сравнения в командном интерпретаторе.
В рамках интерпретатора Bash, как и в повседневном понимании людей, все объекты файловой системы являются, тем, чем они есть, каталогами, текстовыми документами и т.д. В этой статье будет рассмотрена проверка наличия файла Bash, а также его проверка на пустоту, и для этого используется команда test.
Команды для каталогов
Существуют конкретные команды, предназначенные для работы с каталогами. Далее будут приведены самые важные из них.
Циклы в скриптах
Преимущество программ в том, что мы можем в несколько строчек указать какие действия нужно выполнить несколько раз. Например, возможно написание скриптов на bash, которые состоят всего из нескольких строчек, а выполняются часами, анализируя параметры и выполняя нужные действия.
Первым рассмотрим цикл for. Вот его синтаксис:
for переменная in список
do
команда
done
Перебирает весь список, и присваивает по очереди переменной значение из списка, после каждого присваивания выполняет команды, расположенные между do и done.
Например, переберем пять цифр:
Или вы можете перечислить все файлы из текущей директории:
for file in $(ls -l); do echo "$file"; done
Как вы понимаете, можно не только выводить имена, но и выполнять нужные действия, это очень полезно когда выполняется создание bash скрипта.
Второй цикл, который мы рассмотрим - это цикл while, он выполняется пока команда условия возвращает код 0, успех. Рассмотрим синтаксис:
while команда условие
do
команда
done
Как видите, все выполняется, команда let просто выполняет указанную математическую операцию, в нашем случае увеличивает значение переменной на единицу.
Хотелось бы отметить еще кое-что. Такие конструкции, как while, for, if рассчитаны на запись в несколько строк, и если вы попытаетесь их записать в одну строку, то получите ошибку. Но тем не менее это возможно, для этого там, где должен быть перевод строки ставьте точку с запятой ";". Например, предыдущий цикл можно было выполнить в виде одной строки:
Переменные и вывод команд
Переменные не были бы настолько полезны, если бы в них невозможно было записать результат выполнения утилит. Для этого используется такой синтаксис:
$( команда )
С помощью этой конструкции вывод команды будет перенаправлен прямо туда, откуда она была вызвана, а не на экран. Например, утилита date возвращает текущую дату. Эти команды эквивалентны:
Понимаете? Напишем скрипт, где будет выводиться hello world и дата:
Теперь вы знаете достаточно о переменных, и готовы создать bash скрипт, но это еще далеко не все. Дальше мы рассмотрим параметры и управляющие конструкции. Напомню, что это все обычные команды bash, и вам необязательно сохранять их в файле, можно выполнять сразу же на ходу.
Команды для файлов
Далее приведены основные команды для осуществления взаимодействия с файлами. Начинающим полезно опробовать каждую из них, чтобы лучше понять принцип работы утилит.
Управляющие конструкции в скриптах
Создание bash скрипта было бы не настолько полезным без возможности анализировать определенные факторы, и выполнять в ответ на них нужные действия. Это довольно-таки сложная тема, но она очень важна для того, чтобы создать bash скрипт.
В Bash для проверки условий есть команда Синтаксис ее такой:
if команда_условие
then
команда
else
команда
fi
Эта команда проверяет код завершения команды условия, и если 0 (успех) то выполняет команду или несколько команд после слова then, если код завершения 1 выполняется блок else, fi означает завершение блока команд.
Но поскольку нам чаще всего нас интересует не код возврата команды, а сравнение строк и чисел, то была введена команда [[, которая позволяет выполнять различные сравнения и выдавать код возврата зависящий от результата сравнения. Ее синтаксис:
[[ параметр1 оператор параметр2 ]]
Для сравнения используются уже привычные нам операторы ,=,!= и т д. Если выражение верно, команда вернет 0, если нет - 1. Вы можете немного протестировать ее поведение в терминале. Код возврата последней команды хранится в переменной $?:
Теперь объединением все это и получим скрипт с условным выражением:
Конечно, у этой конструкции более мощные возможности, но это слишком сложно чтобы рассматривать их в этой статье. Возможно, я напишу об этом потом. А пока перейдем к циклам.
Проверка наличия файла
Проверка файла Bash на то, является ли данный объект файлом (то есть существует ли файл), выполняется с помощью параметра -f.
Пример работы кода:
В сценарии проверяется, является ли $HOME файлом. Результат проверки отрицательный, после чего проверяется настоящий файл .bash_history, что уже возвращает истину.
На заметку: на практике предпочтительнее использовать сначала проверку на наличие объекта как такового, а затем — на его конкретный тип. Так можно избежать различных ошибок или неожиданных результатов работы программы.
Проверка строки на пустое значение
Сравнение с помощью операторов -z и -n применяется для определения наличия содержимого в переменной. Таким образом, вы можете найти пустые строки bash. Пример:
Результат работы кода:
В этом примере создаются две строковые переменные — val1 и val2. Операция -n определяет, имеет ли переменная val1 ненулевую длину, а -z проверяет val2 и val3 на нулевую. Примечательно то, что последняя не была определена до момента сравнения, но интерпретатор считает, что её длина всё же равна нулю. Такой нюанс следует учитывать при различных проверках сценариев. И, если нет уверенности в том, какое значение содержится в переменной и задано ли оно вообще, стоит проверить её с помощью оператора -n или -z и лишь затем использовать по назначению.
Стоит обратить внимание и на функцию -n. Если ей для проверки будет передана необъявленная или пустая переменная, будет возвращена истина, а не ложь. Для таких случаев следует заключать проверяемую строку (переменную) в двойные кавычки, чтобы выглядело это так:
Сравнение строк по алфавиту на Bash
Задача усложняется при попытке определить, является ли строка предшественницей другой строки в последовательности сортировки по возрастанию. Люди, пишущие сценарии на языке командного интерпретатора bash, нередко сталкиваются с двумя проблемами, касающимися операций "больше" и "меньше" относительно сравнения строк Linux, у которых достаточно простые решения:
Во-первых, символы "больше" и "меньше" нужно экранировать, добавив перед ними обратный слэш (\), потому что в противном случае в командном интерпретаторе они будут расцениваться как символы перенаправления, а строки — как имена файлов. Это один из тех случаев, когда отследить ошибку достаточно сложно.
Что получится, если сравнить строки bash:
Как видно, один лишь символ "больше" в своём непосредственном виде привёл к неправильным результатам, хотя и не было сформировано никаких ошибок. В данном случае этот символ привёл к перенаправлению потока вывода, поэтому никаких синтаксических ошибок не было обнаружено и, как результат, был создан файл с именем hockey:
Для устранения этой ошибки нужно экранировать символ ">", чтобы условие выглядело следующим образом:
Тогда результат работы программы будет правильным:
Во-вторых, упорядочиваемые с помощью операторов "больше" и "меньше" строки располагаются иначе, чем это происходит с командой sort. Здесь проблемы сложнее поддаются распознаванию, и с ними вообще можно не столкнуться, если при сравнении не будет учитываться регистр букв. В команде sort и test сравнение происходит по разному:
Результат работы кода:
В команде test строки с прописными буквами вначале будут предшествовать строкам со строчными буквами. Но если эти же данные записать в файл, к которому потом применить команду sort, то строки со строчными буквами будут идти раньше:
Разница их работы заключается в том, что в test для определения порядка сортировки за основу взято расположение символов по таблице ASCII. В sort же используется порядок сортировки, указанный для параметров языка региональных установок.
Генерация имён файлов в Bash
Иногда пользователю приходится работать с несколькими файлами одновременно, например, при выполнении переноса документов в другой каталог. Это станет проблемой, если элементов десятки или сотни и среди них нужно отобрать определённые.
Для решения поставленной задачи можно попробовать использование шаблонного выражения, позволяющего Bash определить необходимые элементы, ориентируясь по наименованию. Этот способ упрощает управление группой файлов путём применения короткой формулировки в команде.
Итак, теперь остаётся разобраться с вопросом составления шаблонов. Сейчас будут приведены основные конструкции для осуществления генерации имён. Чаще всего для отбора файлов применяется символ: « * ». В случае использования этого знака в чистом виде, Bash выберет все элементы в каталоге без исключений.
Для примера, чтобы из этого каталога отобрать файлы: file1, file2, file3, следует воспользоваться шаблоном:
Символ звёздочки позволяет командному интерпретатору выделить все файлы, начинающиеся с «file». При этом последующая часть наименования будет проигнорирована.
Знак « * » можно использовать также в начале или с обеих сторон шаблона.
Кроме того, сгенерировать имена можно, взяв за основу расширение файла. Например:
Основы скриптов
Скрипт или как его еще называют - сценарий, это последовательность команд, которые по очереди считывает и выполняет программа-интерпретатор, в нашем случае это программа командной строки - bash.
Скрипт - это обычный текстовый файл, в котором перечислены обычные команды, которые мы привыкли вводить вручную, а также указанна программа, которая будет их выполнять. Загрузчик, который будет выполнять скрипт не умеет работать с переменными окружения, поэтому ему нужно передать точный путь к программе, которую нужно запустить. А дальше он уже передаст ваш скрипт этой программе и начнется выполнение.
Простейший пример скрипта для командной оболочки Bash:
Утилита echo выводит строку, переданную ей в параметре на экран. Первая строка особая, она задает программу, которая будет выполнять команды. Вообще говоря, мы можем создать скрипт на любом другом языке программирования и указать нужный интерпретатор, например, на python:
В первом случае мы прямо указали на программу, которая будет выполнять команды, в двух следующих мы не знаем точный адрес программы, поэтому просим утилиту env найти ее по имени и запустить. Такой подход используется во многих скриптах. Но это еще не все. В системе Linux, чтобы система могла выполнить скрипт, нужно установить на файл с ним флаг исполняемый.
Этот флаг ничего не меняет в самом файле, только говорит системе, что это не просто текстовый файл, а программа и ее нужно выполнять, открыть файл, узнать интерпретатор и выполнить. Если интерпретатор не указан, будет по умолчанию использоваться интерпретатор пользователя. Но поскольку не все используют bash, нужно указывать это явно.
chmod ugo+x файл_скрипта
Теперь выполняем нашу небольшую первую программу:
Все работает. Вы уже знаете как написать маленький скрипт, скажем для обновления. Как видите, скрипты содержат те же команды, что и выполняются в терминале, их писать очень просто. Но теперь мы немного усложним задачу. Поскольку скрипт, это программа, ему нужно самому принимать некоторые решения, хранить результаты выполнения команд и выполнять циклы. Все это позволяет делать оболочка Bash. Правда, тут все намного сложнее. Начнем с простого.
Перенаправление данных
Перенаправление ввода-вывода в файл осуществляется с помощью специальных знаков. Для вывода используются « > » и « >> », а для ввода — « < ».
Пример вывода « ls » в файл, а не на экран:
Новый файл создаётся автоматически. В случае существования элемента с таким же наименованием, произойдёт перезапись. Чтобы этого избежать, необходимо использовать « >> ». Тогда данные будут дописываться в документ.
Пример ввода, при котором информация выносится из файла с помощью команды « sort »:
Переменные в скриптах
Написание скриптов на Bash редко обходится без сохранения временных данных, а значит создания переменных. Без переменных не обходится ни один язык программирования и наш примитивный язык командной оболочки тоже.
Возможно, вы уже раньше встречались с переменными окружения. Так вот, это те же самые переменные и работают они аналогично.
Например, объявим переменную string:
Значение нашей строки в кавычках. Но на самом деле кавычки не всегда нужны. Здесь сохраняется главный принцип bash - пробел - это специальный символ, разделитель, поэтому если не использовать кавычки world уже будет считаться отдельной командой, по той же причине мы не ставим пробелов перед и после знака равно.
Чтобы вывести значение переменной используется символ $. Например:
Модифицируем наш скрипт:
Bash не различает типов переменных так, как языки высокого уровня, например, С++, вы можете присвоить переменной как число, так и строку. Одинаково все это будет считаться строкой. Оболочка поддерживает только слияние строк, для этого просто запишите имена переменных подряд:
Обратите внимание, что как я и говорил, кавычки необязательны если в строке нет спецсимволов. Присмотритесь к обоим способам слияния строк, здесь тоже демонстрируется роль кавычек. Если же вам нужны более сложные способы обработки строк или арифметические операции, это не входит в возможности оболочки, для этого используются обычные утилиты.
Выводы
Теперь вы понимаете основы создания скрипта в linux и можете написать нужный вам скрипт, например, для резервного копирования. Я пытался рассматривать bash скрипты с нуля. Поэтому далеко не все аспекты были рассмотрены. Возможно, мы еще вернемся к этой теме в одной из следующих статей.
Часто при написании скриптов под bash необходимо проверять результаты выполнения тех или иных команд.
Это немного подправленная выдержка из этой статьи .
Скобки
[ — является специальной встроенной командой test воспринимающей свои аргументы как выражение сравнения или файловую проверку […..].
[[ — расширенный вариант от «[«, является зарезервированным словом, а не командой, его bash выполняет как один элемент с кодом возврата. Внутри «[[….]]» разрешается выполнение операторов &&, || которые приводят к ошибке в обычных скобках «[….]» тем самым вариант с двойной скобкой более универсален.
(( — является арифметическими выражениями, которое так же возвращают код 0. Тем самым такие выражения могут участвовать в операциях сравнения.
Приведу список логических операторов, которые используются для if|then|else:
-z – строка пуста
-n – строка не пуста
=, ( == ) – строки равны
!= – строки неравны
-eq – равно
-ne – неравно
-gt,(>) – больше
-ge,(>=) - больше или равно
! - отрицание логического выражения
-a,(&&) – логическое «И»
-o,(||) -логическое «ИЛИ»
Конструкции простой проверки if|then
Другими словами:
если проверяемое_выражение_или_команды_верны; то выполняем команды закрываем если
Пример 1
Часто встречается в скриптах проверка — «существует ли файлы или каталоги» на их примере покажу работу
Пример 2
Пример 3
&& - логическое «и», если первый путь «истина» проверяем второй, если он тоже «истина», то выполняем команды (echo)
-f – ключ проверки на существования файла (о них чуть ниже)
Конструкции простой проверки if|then|else
если проверяемое_выражение_или_команды_верны; то команды 1 иначе команды 2 закрываем если
Пример 4
Возможно не лучший пример, нас интересует именно ответ 0 или 1. В результате печатается в консоль «Тест» и «0» потому что команда «echo Тест» успешна и это «истина».
Примеры «существуют ли файл?»
Пример 5
Если файл bashrc существует, то печатает в консоль «Файл существует!», иначе печатает «Файл не существует!»
Поиграйте с именем проверяемого файла
Пример 6
Ключи к файлам и каталогам
[ -ключ “путь” ]
[ -e “путь каталогу_или_файлу”] – существует ли файл или каталог.
[ -r “путь к файлу/каталогу”] – доступен ли файл/каталог для чтения.
[ -f “путь к файлу/каталогу”] – существует ли файл.
[ -d “путь к каталогу”] – существует ли каталог.
Полное описание возможных применений различных скобок, правильное расставление кавычек уходит далеко от темы, поэтому могу посоветовать обратится к руководству Advanced Bash Scripting
Арифметика
Пример 7
Если оператор > использовать внутри [[….]], он рассматривается как оператор сравнения строк, а не чисел. Поэтому операторам > и < для сравнения чисел лучше заключить в круглые скобки.
Используем круглые скобки для математического сравнение. Если «3» меньше «6» печатаем «Да».
Пример 8
Использование команды test, коей являются квадратные скобки. Если «3» меньше «6» печатаем «Да».
Можно использовать и двойные квадратные скобки, это расширенный вариант команды test, эквивалентом которой является «[ ]». Если «3» меньше «6» печатаем «Да».
Пример 9
Используем двойные квадратные скобки, потому что применяем оператор «&&». Если первое выражение 2 = 2 (истина) тогда выполняем второе, и если оно тоже 2=2 (истина), печатаем «Верно»
Если первое выражение 2 = 2 (истина) тогда выполняем второе, и если переменная «b» не равна двум (ложь), печатаем «Не верно»
Можно конечно сделать проще, нам главное понять принцип if|then и else, не стесняйтесь менять, подставляя свои значения.
Вложение нескольких проверок
Bash позволяет вкладывать в блок несколько блоков
Построения многоярусных конструкций
Для построения многоярусных конструкции, когда необходимо выполнять множество проверок лучше использовать elif — это краткая форма записи конструкции else if.
При написании сценариев на Bash не только опытные программисты, но и новички в области командного интерпретатора Bash сталкиваются с работой со строками. Наиболее часто это необходимо при считывании команд, вводимых пользователем в качестве аргументов для исполняемого сценария, а также при обработке текстовых файлов. И один из необходимых приёмов в таком случае — это сравнение строк.
В данной статье будет рассмотрено сравнение строк Bash, а также некоторые нюансы по использованию операций сравнения и решению часто встречающихся ошибок.
Проверка существования файла Bash
Начать стоит с простого и более общего метода. Параметр -e позволяет определить, существует ли указанный объект. Не имеет значения, является объект каталогом или файлом.
Пример работы кода:
Работа с файлами и каталогами
Работа с файлами и каталогами в Linux через Bash осуществляется с учетом иерархического принципа их классификации. Иерархическая структура файловой системы Linux напоминает «дерево». Существует корневой каталог, который является начальным для всей ОС, а в нём, соответственно, масса других подкаталогов.
Такой же принцип используется для командной строки. Файлы и каталоги берут начало из корневого узла « / », который является начальной точкой для всех элементов.
Ниже представлен стандартный перечень подкаталогов, встречающийся в большинстве UNIX-систем.
Каталог | Содержимое |
/bin | Бинарные версии файлов (в том числе для командной оболочки). |
/dev | Псевдофайлы, представляющие собой аппаратные средства, подключённые к устройству. |
/etc | Большая часть конфигурационных файлов. |
/lib | Библиотеки для системных приложений. |
/opt | Необязательные компоненты системы или приложения. |
/tmp | Временные файлы. |
/usr | Пользовательские компоненты. |
/var | Файлы приложений (в том числе системные журналы, кэши и т. д.). |
Список основных команд
- pwd — вывод полного пути к текущему каталогу.
- cd — переход с текущего каталога на домашний пользовательский.
- cd dirname — перейти в папку «dirname».
- cd / — переход по директориям относительно корневого каталога.
- ls — просмотреть список файлов в каталоге.
- ls -d */ — просмотреть список папок в текущем каталоге.
- ls dirname — вывод содержимого каталога «dirname» на экран.
- mkdir dirname — создать папку с наименованием «dirname».
- rmdir dirname — удалить папку «dirname».
- rm -rf dirname — удалить папку «dirname» с её содержимым (опция -r) без предупреждения пользователя (опция -f).
- du -h dirname — размер папки «dirname».
Помимо этого, существуют полезные сокращения. Например, текущая директория обозначается с помощью « . ». Знак « .. » позволяет задействовать родительский каталог. Для представления домашней директории используется « ~ ».
Пример использования сокращений:
Параметры скрипта
Не всегда можно создать bash скрипт, который не зависит от ввода пользователя. В большинстве случаев нужно спросить у пользователя какое действие предпринять или какой файл использовать. При вызове скрипта мы можем передавать ему параметры. Все эти параметры доступны в виде переменных с именами в виде номеров.
Переменная с именем 1 содержит значение первого параметра, переменная 2, второго и так далее. Этот bash скрипт выведет значение первого параметра:
Сравнение строк Bash
Данные операции позволяют определить, являются ли сравниваемые строки одинаковыми:
Результат работы сценария:
При проверке на равенство с помощью команды test (синоним квадратным скобкам [ ]) учитываются все пунктуационные знаки и различия в регистре букв сравниваемых строк.
Некоторые особенности сравнения строк с шаблонами:
Например проверка строки bash на то, начинается ли она с символа y:
Результат выполнения кода:
Сценарий вывел 0 (ноль), так как мы потребовали вывести код ошибки последней выполненной инструкции. А код 0 означает, что сценарий выполнился без ошибок. И действительно — переменная $x содержит строку yandex, которая начинается с символа "y". В противном случае может писаться "1". Это довольно удобный способ отладки сценариев.
Список основных команд
- touchfile — создать файл.
- realpath file — узнать абсолютный путь к файлу.
- stat file1 — получение информации о «file1» (размер файла, дата создания файла и т. д.) и проверка существования файла.
- cat > file — запись в файл.
- catfile — чтение файла.
- echo текст >> file — дописать в файл текст.
- find file — поиск файла.
- mcedit file — редактирование файла (также можно использовать редакторы Nano, Vim и другие).
- cat file1 file2 > file12 — объединение файлов.
- sh filename — запустить файл со сценарием Bash.
- ./filename — запустить исполняемый файл.
- cp file1 file2 — копировать файл «file1» с переименованием на «file2». Произойдёт замена файлов, если элемент с таким же названием существует.
- mv file1 file2 — переименовать файл «file1» в «file2».
- mv filename dirname — переместить файл «filename» в каталог «dirname».
- less filename — открыть файл в окне терминала.
- file filename — определение типа файла.
- head filename — вывод нескольких начальных строк из файла на экран (построчное чтение файла). По умолчанию строк 10.
- tail filename — вывод нескольких конечных строк из файла на экран.
- diff file1 file2 — сравнение файлов.
- grep text filename — поиск и вывод строк из файла, содержащих «text».
- rm filename — удалить файл.
Подробную информацию об утилитах можно получить, воспользовавшись справочной службой: « man ».
Пример получения справки по работе с программой rm: « man rm ».
Проверка файла на пустоту
Чтобы определить, является ли файл пустым, нужно выполнить проверку с помощью параметра -s. Это особенно важно, когда файл намечен на удаление. Здесь нужно быть очень внимательным к результатам, так как успешное выполнение этого параметра указывает на наличие данных.
Результат работы программы:
В этом скрипте файл создаётся командой touch, и при первой проверке на пустоту возвращается отрицательный результат. Затем в него записываются данные в виде команды date, после чего повторная проверка файла возвращает истину.
Читайте также: