Bash краткое руководство

Время на прочтение
5 мин

Количество просмотров 1.3M

Безусловно, все те кто общается с ОС Linux хоть раз да имели дело(во всяком случае слышали точно) с командной оболочкой BASH. Но BASH не только командная оболочка, это еще и превосходный скриптовый язык программирования.
Цель этой статьи — познакомить поближе юзеров с bash, рассказать про синтаксис, основные приемы и фишки языка, для того чтобы даже обычный пользователь смог быстренько написать простой скрипт для выполнения ежедневной(-недельной, -месячной) рутинной работы или, скажем, «на коленке» наваять скриптик для бэкапа директории.

Введение

BASH

— Bourne-Again SHell (что может переводится как «перерожденный шел», или «Снова шел Борна(создатель sh)»), самый популярный командный интерпретатор в юниксоподобных системах, в особенности в GNU/Linux. Ниже приведу ряд встроенных команд, которые мы будем использовать для создания своих скриптов.

break выход из цикла for, while или until
continue выполнение следующей итерации цикла for, while или until
echo вывод аргументов, разделенных пробелами, на стандартное устройство вывода
exit выход из оболочки
export отмечает аргументы как переменные для передачи в дочерние процессы в среде
hash запоминает полные имена путей команд, указанных в качестве аргументов, чтобы не искать их при следующем обращении
kill посылает сигнал завершения процессу
pwd выводит текущий рабочий каталог
read читает строку из ввода оболочки и использует ее для присвоения значений указанным переменным.
return заставляет функцию оболочки выйти с указанным значением
shift перемещает позиционные параметры налево
test вычисляет условное выражение
times выводит имя пользователя и системное время, использованное оболочкой и ее потомками
trap указывает команды, которые должны выполняться при получении оболочкой сигнала
unset вызывает уничтожение переменных оболочки
wait ждет выхода из дочернего процесса и сообщает выходное состояние.

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

Что необходимо знать с самого начала

1. Любой bash-скрипт должен начинаться со строки:

#!/bin/bash
в этой строке после #! указывается путь к bash-интерпретатору, поэтому если он у вас установлен в другом месте(где, вы можете узнать набрав whereis bash) поменяйте её на ваш путь.
2. Коментарии начинаются с символа # (кроме первой строки).
3. В bash переменные не имеют типа(о них речь пойдет ниже)

Переменные и параметры скрипта

Приведу как пример небольшой пример, который мы разберем:

#!/bin/bash
#указываем где у нас хранится bash-интерпретатор
parametr1=$1 #присваиваем переменной parametr1 значение первого параметра скрипта
script_name=$0 #присваиваем переменной script_name значение имени скрипта
echo "Вы запустили скрипт с именем $script_name и параметром $parametr1" # команда echo выводит определенную строку, обращение к переменным осуществляется через $имя_переменной.
echo 'Вы запустили скрипт с именем $script_name и параметром $parametr1' # здесь мы видим другие кавычки, разница в том, что в одинарных кавычках не происходит подстановки переменных.
exit 0 #Выход с кодом 0 (удачное завершение работы скрипта)

Результат выполнения скрипта:

ite@ite-desktop:~$ ./test.sh qwerty
Вы запустили скрипт с именем ./test.sh и параметром qwerty
Вы запустили скрипт с именем $script_name и параметром $parametr1

После того как мы познакомились как использовать переменные и передавать скрипту параметры, время познакомиться с зарезервированными переменными:

$DIRSTACK - содержимое вершины стека каталогов
$EDITOR - текстовый редактор по умолчанию
$EUID - Эффективный UID. Если вы использовали программу su для выполнения команд от другого пользователя, то эта переменная содержит UID этого пользователя, в то время как...
$UID - ...содержит реальный идентификатор, который устанавливается только при логине.
$FUNCNAME - имя текущей функции в скрипте.
$GROUPS - массив групп к которым принадлежит текущий пользователь
$HOME - домашний каталог пользователя
$HOSTNAME - ваш hostname
$HOSTTYPE - архитектура машины.
$LC_CTYPE - внутренняя переменная, котороя определяет кодировку символов
$OLDPWD - прежний рабочий каталог
$OSTYPE - тип ОС
$PATH - путь поиска программ
$PPID - идентификатор родительского процесса
$SECONDS - время работы скрипта(в сек.)
$# - общее количество параметров переданных скрипту
$* - все аргументы переданыне скрипту(выводятся в строку)
$@ - тоже самое, что и предыдущий, но параметры выводятся в столбик
$! - PID последнего запущенного в фоне процесса
$$ - PID самого скрипта

Условия

Условные операторы, думаю, знакомы практически каждому, кто хоть раз пытался на чем-то писать программы. В bash условия пишутся след. образом (как обычно на примере):
#!/bin/bash
source=$1 #в переменную source засовываем первый параметр скрипта
dest=$2 #в переменную dest засовываем второй параметр скрипта

if [[ "$source" -eq "$dest" ]] # в ковычках указываем имена переменных для сравнения. -eq - логическое сравнение обозначающие "равны"
then # если они действительно равны, то
echo "Применик $dest и источник $source один и тот же файл!" #выводим сообщение об ошибке, т.к. $source и $dest у нас равны
exit 1 # выходим с ошибкой (1 - код ошибки)
else # если же они не равны
cp $source $dest # то выполняем команду cp: копируем источник в приемник
echo "Удачное копирование!"
fi #обозначаем окончание условия.


Результат выполнения скрипта:
ite@ite-desktop:~$ ./primer2.sh 1 1
Применик 1 и источник 1 один и тот же файл!
ite@ite-desktop:~$ ./primer2.sh 1 2
Удачное копирование!

Структура if-then-else используется следующим образом:
if <команда или набор команд возвращающих код возврата(0 или 1)>
then
<если выражение после if истино, то выполняется этот блок>
else
<если выражение после if ложно, тот этот>
В качестве команд возвращающих код возврата могут выступать структуры [[ , [ , test, (( )) или любая другая(или несколько) linux-команда.
test - используется для логического сравнения. после выражения, неоьбходима закрывающая скобка "]"
[ - синоним команды test
[[ - расширенная версия "[" (начиная с версии 2.02)(как в примере), внутри которой могут быть использованы || (или), & (и). Долна иметь закрывающуб скобку "]]"
(( )) - математическое сравнение.
для построения многоярусных условий вида:
if ...
then ....
else
if ....
then....
else ....

для краткости и читаемости кода, можно использовать структуру:
if ..
then ...
elif ...
then ...
elif ...

Условия. Множественный выбор

Если необходимо сравнивать какоую-то одну переменную с большим количеством параметров, то целесообразней использовать оператор case.
#!/bin/bash
echo "Выберите редатор для запуска:"
echo "1 Запуск программы nano"
echo "2 Запуск программы vi"
echo "3 Запуск программы emacs"
echo "4 Выход"
read doing #здесь мы читаем в переменную $doing со стандартного ввода

case $doing in
1)
/usr/bin/nano # если $doing содержит 1, то запустить nano
;;
2)
/usr/bin/vi # если $doing содержит 2, то запустить vi
;;
3)
/usr/bin/emacs # если $doing содержит 3, то запустить emacs
;;
4)
exit 0
;;
*) #если введено с клавиатуры то, что в case не описывается, выполнять следующее:
echo "Введено неправильное действие"

esac #окончание оператора case.


Результат работы:
ite@ite-desktop:~$ ./menu2.sh
Выберите редатор для запуска:
1 Запуск программы nano
2 Запуск программы vi
3 Запуск программы emacs
4 Выход

После выбор цифры и нажатия Enter запуститься тот редактор, который вы выбрали(если конечно все пути указаны правильно, и у вас установлены эти редакторы :) )
Прведу список логических операторв, которые используются для конструкции if-then-else-fi:
-z # строка пуста
-n # строка не пуста
=, (==) # строки равны
!= # строки неравны
-eq # равно
-ne # неравно
-lt,(< ) # меньше
-le,(<=) # меньше или равно
-gt,(>) #больше
-ge,(>=) #больше или равно
! #отрицание логического выражения
-a,(&&) #логическое «И»
-o,(||) # логическое «ИЛИ»

С основами языка и условиями мы разобрались, чтобы не перегружать статью, разобью её на несколько частей(допустим на 3). Во второй части разберем операторы цикла и выполнение математических операций.

UPD: Исправил некоторые ошибки
UPD: Обновил часть про условия if-then-else

Статьи на unix-admin.su

В данной шпаргалке затрагиваются следующие темы: введение в оболочку, навигация, основные команды, переменные окружения, коннекторы, конвейеры, перенаправление ввода/вывода, права доступа и комбинации клавиш. 

Оболочка Bash: введение

Оболочка, или шелл (shell) — это программа, в нашем случае названная «bash», что является сокращением от Bourne Again Shell. Оболочка принимает ваши команды и передаёт их операционной системе. Для взаимодействия с системой используются терминалы, такие как gnome-terminal, eterm, nxterm и т. п.

Навигация

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

pwd

Команда pwd, сокращение от print working directory, отображает текущее местоположение в структуре каталогов.

cd

Команда cd позволяет перейти в новый каталог.

Синтаксис Объяснение
cd Перемещение в домашний каталог
cd ~ Перемещение в домашний каталог
cd .. Перемещение на один уровень выше
cd - Перемещение в предыдущий каталог
cd Directory1 Перемещение в каталог Directory1
cd Directory1/Directory2 Перемещение в каталог Directory2 по указанному пути

mkdir

Команда mkdir создаёт новый каталог в текущем каталоге.

Основные команды

man

Команда man отображает руководства по командам. Например, следующая команда выдаст всю информацию о команде cat:

$ man cat

cat

Команда cat считывает файл, переданный как аргумент, и выводит его содержимое по стандартному каналу вывода. Передача нескольких файлов в виде аргумента приведёт к выводу конкатенированного содержимого всех файлов.

echo

Команда echo выводит свои аргументы по стандартному каналу вывода.

$ echo Hello World
  Hello World

Если вызвать echo без аргументов, будет выведена пустая строка.

head

Команда head читает первые 10 строк любого переданного текста и выводит их по стандартному каналу. Число выводимых строк можно изменить:

$ head -50 test.txt

tail

Команда tail работает аналогично команде head, но читает строки с конца:

$ tail -50 test.txt

Также можно просматривать добавляемые к файлу строки в режиме реального времени при помощи флага -f:

$ tail -f test.txt

less

Команда less позволяет перемещаться по переданному файлу или куску текста, причём в обоих направлениях.

$ less test.txt
$ ps aux | less

Подробнее о назначении символа | будет рассказано ниже в разделе команды history.

Обычные сочетания клавиш Описание
G Перемещает в конец файла
g Перемещает в начало файла
:50 Перемещает на 50 строку файла
q Выход из less
/searchterm Поиск строки, совпадающей с ‘searchterm’, ниже текущей строки
/ Перемещает на следующий подходящий результат поиска
?searchterm Поиск строки, совпадающей с ‘searchterm’, выше текущей строки
? Перемещает на следующий подходящий результат поиска
up Перемещает на одну строку выше
down Перемещает на одну строку ниже
pageup Перемещает на одну страницу выше
pagedown Перемещает на одну страницу ниже

true

Команда true всегда возвращает ноль в качестве выходного статуса для индикации успеха.

false

Команда false всегда возвращает не-ноль в качестве выходного статуса для индикации неудачи.

$?

$? — это переменная, которая содержит выходной статус последней запущенной команды. Под статусом обычно понимается код возврата программы. 0 означает успешное выполнение программы, любое значение большее 0 отражает тот факт, что в процессе выполнения возникли некоторые ошибки. Кстати, именно поэтому в bash истинной (true) считается 0, а все, что не 0 — ложью (false):

$ true
$ echo $?
  0
$ false
$ echo $?
  1

grep

Команда grep занимается поиском переданной строки в указанном файле:

$ cat users.txt
  user:student password:123
  user:teacher password:321
$ grep 'student` file1.txt
  user:student password:123

grep также может принимать несколько файлов и регулярных выражений для уточнения формата текста.

Обычные флаги Описание
-i Отключение чувствительности к регистру
-r Рекурсивный поиск по директориям
-w Поиск только целых слов
-c Вывод количества найденных элементов
-n Вывод всей строки, содержащей запрос
-v Вывод инвертированного совпадения

Также можно ознакомиться с руководством по regex. У нас на сайте тоже есть руководство по «регуляркам» в Python для новичков.

sed

Команда sed — это потоковый редактор, преобразующий входные текстовые данные. Обычно её используют для замены выражений так: s/regexp/replacement/g. Например, следующий код заменит все слова «Hello» на «Hi»:

$ cat test.txt
  Hello World
$ sed 's/Hello/Hi/g' test.txt
  Hi World

Также вы можете ознакомиться с руководством по sed.

history

Команда history выводит историю командной строки. Обычно её используют вместе с командой grep для поиска конкретной команды. Например, следующий код найдёт все команды, содержащие строку g++:

$ history | grep g++
  155  g++ file1.txt
  159  g++ file2.txt

Здесь также используется символ | — это так называемый конвейер (pipe). Благодаря ему можно перенаправлять вывод одной команды на вход другой — таким образом в примере выше вся история, которая в обычном режиме выводится командой history прямо в вывод терминала, будет перенаправлена в grep в качестве входных данных. Мы не увидим вывода команды history, но увидим вывод команды grep.

Это может быть довольно сложно для понимания без практики, поэтому поэкспериментируйте самостоятельно, например с командами lshistoryps (описана ниже), перенаправляя их вывод в grepsed или less, например.

export

Команда export устанавливает переменные окружения для передачи дочерним процессам. Например, так можно передать переменную name со значением student:

$ export name=student

ps

Команда ps выводит информацию о запущенных процессах.

$ ps
  PID TTY          TIME CMD
  35346 pts/2    00:00:00 bash

Выводится четыре элемента:

  • ID процесса (PID),
  • тип терминала (TTY),
  • время работы процесса (TIME),
  • имя команды, запустившей процесс (CMD).

awk

Команда awk находит и заменяет текст в файлах по заданному шаблону: awk 'pattern {action}' test.txt

wget

Команда wget скачивает файлы из Сети и помещает их в текущий каталог.

$ wget https://github.com/mikeizbicki/ucr-cs100

nc

Команда nc — это утилита для отладки сети. Также можно ознакомиться с руководством по nc.

ping

Команда ping тестирует сетевое подключение.

$ ping google.com
  PING google.com (74.125.224.34) 56(84) bytes of data.
  64 bytes from lax17s01-in-f2.1e100.net (74.125.224.34): icmp_req=1 ttl=57 time=7.82 ms
  --- google.com ping statistics ---
  1 packets transmitted, 1 received, 0% packet loss, time 8ms
  rtt min/avg/max/mdev = 7.794/8.422/10.792/0.699 ms

Статистика в конце показывает количество подключений, совершённых до завершения команды, и время их выполнения.

git

Git — это популярная система контроля версий. Также можно ознакомиться с руководством по git и нашими материалами.

Переменные окружения

Переменные окружения — это именованные переменные, содержащие значения, используемые одним или несколькими приложениями.

Переменная PATH содержит список каталогов, в которых система ищет исполняемые файлы.

Переменная HOME содержит путь к домашнему каталогу текущего пользователя.

Коннекторы

Коннекторы позволяют запускать несколько команд одновременно.

Коннектор Описание
&& Первая команда исполняется всегда, вторая — только в случае успешного завершения первой
|| Первая команда исполняется всегда, вторая — только в случае неудачного завершения первой
; Команды исполняются всегда
$ true && echo Hello
  Hello
$ false || echo Hello
  Hello
$ echo Hello ; ls
  Hello
  test.txt file1.txt file2.txt

Конвейеры

Конвейеры, или пайпы, позволяют соединять входные и выходные каналы различных команд. В следующем примере вывод команды ls будет передан в head , и в результате будет напечатано лишь 10 первых элементов.

$ ls -l | head

Перенаправление ввода/вывода

Перенаправление вывода

Для стандартного перенаправления вывода используются символы > и >>.

Например, этот код передаст вывод ls в файл, а не на экран:

$ ls > files.txt
$ cat files.txt
  file1.cpp sample.txt

Если файл не существует, он создаётся, а если существует, то перезаписывается. Во избежание перезаписи стоит использовать команду >> — она дописывает данные в конец файла.

Перенаправление ввода

Для стандартного перенаправления вывода используется символ <. В следующем примере sort берет входные данные из файла, а не с клавиатуры:

$ cat files.txt
  c
  b
$ sort < files.txt
  b
  c

Команда sort выводит содержимое файла на экран, поскольку мы не перенаправили выход. Это можно сделать так:

$ sort < files.txt > files_sorted.txt

Продвинутое перенаправление

Добавление & к > приводит к перенаправлению как стандартного потока выхода, так и потока ошибок. Например, файл test.cpp выведет строку stdout в cout и строку stderr в cerr.

$ g++ test.cpp
$ ./a.out >& test.txt
$ cat test.txt
  stdout
  stderr

Если вы хотите вывести конкретный файловый дескриптор, вы можете приписать его номер к >.

Имя Дескриптор Описание
stdin 0 Стандартный поток ввода
stdout 1 Стандартный поток вывода
stderr 2 Стандартный поток вывода ошибок

Например, для перенаправления stderr в test.txt нужно сделать следующее:

$ g++ test.cpp
$ ./a.out 2> test.txt
  stdout
$ cat test.txt
  stderr

Права доступа

Команда ls -l выводит много информации о правах доступа к каждому файлу:

$ ls -l test.txt
  -rw-rw-r--  1  user  group  1097374 January 26 2:48 test.txt
Вывод в примере Описание / возможные выводы
Тип файла:
- файл
d каталог
rw- Права доступа владельца файла
rw- Права доступа членов группы-владельца файла
r— Права доступа прочих пользователей
user Имя владельца файла
group Имя группы-владельца файла

chmod

Команда chmod изменяет права доступа файла. Вот типичные сочетания флагов для изменения прав конкретных пользователей:

Буква Пользователь
u Владелец
g Член группы
o Прочие пользователи
a Все пользователи

Вы можете вызвать chmod с описанием действий над конкретным файлом. Символ - обозначает удаление прав, символ + — добавление. Следующий пример сделает файл доступным для чтения и записи владельцу и группе:

$ chmod ug+rw test.txt
$ ls -l test.txt
  -rw-rw----  1  user  group  1097374 January 26 2:48 test.txt

Кроме того, chmod можно использовать с восьмеричными числами, где 1 — это наличие прав, а 0 — отсутствие:

rwx = 111 = 7
rw- = 110 = 6
r-x = 101 = 5
r-- = 100 = 4

Следующая команда сработает так же, как и предыдущая:

$ chmod 660 test.txt

Также можно ознакомиться с руководством по правам доступа.

Сочетания клавиш

Сочетание Описание
CTRL-A Перемещение курсора в начало строки
CTRL-E Перемещение курсора в конец строки
CTRL-R Поиск по истории
CTRL-W Вырезать последнее слово
CTRL-U Вырезать всё до курсора
CTRL-K Вырезать всё после курсора
CTRL-Y Вернуть последнюю вырезанную строку
CTRL-_ Отмена
CTRL-L Очистка экрана терминала

По материалам Bash-Cheatsheet

Перевели статью, которая поможет лучше понять, как работает bash, а значит, сэкономить время и уменьшить количество ошибок. Далее текст от лица автора.

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

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

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

Язык программирования, на котором писала ваша бабушка

Bash создан Брайаном Фоксом (легендарный и недооцененный парень) и выпущен в 1989 году как open source замена для Bourne Shell, вышедшей в 1976 году. Его название является аббревиатурой от Bourne Again SHell.

Если вы привыкли писать на любом другом языке программирования, bash (и сценарии оболочки в целом) не будут для вас интуитивно понятными. Синтаксис не запоминающийся, переменные странные, область видимости — полная дичь, и поток управления никогда не делает то, что вы думаете.

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

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

Примечание: я предполагаю, что вы обладаете некоторыми предварительными знаниями в программировании и сценариях командной оболочки. Если вы только начинаете изучение — вот хороший ресурс для начала. Я предполагаю, что вы, по крайней мере, знаете, как использовать терминал и следующие команды: ls, cd, pwd, cat, grep и написали (или попытались написать) один или два сценария.

Кстати, поскольку эта статья относится к миру Linux и операционных систем, у меня есть примечание для тех, кто занимается этими вопросами дольше меня: нормально (даже рекомендуется!) исправлять меня, если я ошибаюсь, просто будьте вежливы.

Версии

Язык сценариев оболочки, c которым большинство из нас работает в настоящее время, — это версия bash для Mac и Linux, используемая для эмуляции терминала в /bin/bash.

Debian (и, соответственно, Ubuntu и Linux Mint) теперь использует другой, но в основном совместимый язык сценариев оболочки (dash) для системных задач. Прим. переводчика: так утверждает автор статьи, но я везде вижу использование bash.

Вы также можете установить zsh в качестве основной оболочки, который в целом похож на bash, но имеет и отличия.

Из-за всех этих небольших вариаций хорошей идеей будет поместить #!/bin/bash (или какой-либо другой язык сценариев оболочки, который вы хотите использовать) вверху файлов, чтобы указать, что сценарий оболочки должен использовать конкретно этот язык, а не какой-либо еще из установленных на сервере.

Указание языка оболочки в заголовке файла сделает его поведение более предсказуемым. Например, ответы на Stack Overflow обычно предполагают, что вы используете именно bash.

Основы

Давайте сначала рассмотрим несколько фундаментальных вещей.

Сценарии оболочки, по сути, представляют собой текстовые потоки, которые передают данные между собой. Они используют философию Unix, заключающуюся в том, чтобы хорошо выполнять одну задачу и объединять крошечные инструменты в более крупные программы по принципу работы конвейера в промышленности. Результат выполнения каждый инструмента передается на вход следующему по порядку.

Синтаксис

Bash использует нестрогий синтаксис; вы можете использовать точку с запятой в конце строки, если хотите, и отступы не влияют на выполнение кода. В нестрогости синтаксиса кроется ловушка. Синтаксис bash важен и очень специфичен. Вдобавок, по сравнению с другими языками, ошибки в синтаксисе трудно диагностировать.

Очень важно правильно использовать пробелы и точки с запятой.

Например, можно получить ошибку “[grep isn’t a valid command”, если забыть поставить пробел внутри квадратных скобок [] или “Unexpected end of file”, когда вы забыли точку с запятой после {}.

При определении переменной пробел между переменной и знаком = и между знаком = и значением приводит к разным результатам. Существует важное различие между одинарными кавычками и двойными.

Синтаксические ошибки всегда выглядят как логические ошибки, что затрудняет выявление опечаток.

Структура

Сценарии оболочки понимают операторы управления выполнением: операторы if, циклы while, циклы for, операторы case и так далее.

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

Вот пример однострочника, который использует управление выполнением без каких-либо операторов if:

tac ~/error.log 
| grep -m1 -E "Error|Running restart" 
| grep -q "Error" 
&& echo "Found error since last restart"

Примечание: обозначают перенос строки, tac похож на cat, но выводит файл в обратном порядке.

Это выглядит уродливо, но эффективно, и иллюстрирует сильные и слабые стороны сценариев оболочки.

Сценарий bash может быть очень кратким и трудным для чтения. Вы можете многое сделать в несколько строк, но когда что-то сломается, может быть трудно понять, почему. Это благословение и проклятие. С большой силой появляется огромный потенциал, чтобы все испортить.

Что такое поток? Что такое команда?

Каждая команда — это программа, которая делает одну вещь. Grep, например, ищет вещи и возвращает строки. Запросы и файлы подаются на вход, найденные строки идут с выхода.

Вы можете подумать: «Да ладно, именно так работает все программирование», но в данном случае все немного сложнее, и это особенно важно понять.

Входы и выходы передаются от команды к команде в виде текстовых потоков. Есть три места, куда эти потоки идут и откуда берутся:

  • stdin: Стандартный ввод.
  • stdout: Стандартный вывод.
  • stderr: Стандартный вывод ошибок.

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

Вы отправляете текст на стандартный вывод с помощью таких команд, как printf и echo. Неопытный программист может думать, что это просто команды для вывода сообщений отладки, как в Python или JavaScript. Это не так.

Потоки позволяют объединять команды и функции. Хороший способ проиллюстрировать это — объяснить, как работают функции.

Функции

Определим функцию:

function hello () {
    printf "Hello World! n"
    local variable="Something n"
    printf "$variable"
    echo some more stuff to print $variable
}

Если запустить в терминале $ hello.sh, вы получите:

Hello World!
Something
some more stuff to print Something

Команды echo и printf отправляют текстовые потоки на стандартный вывод. Если вы запустите нашу функцию приветствия из терминала, stdout будет выведен на вашу консоль.

Мы можем перенаправить вывод и отправить его в файл или в качестве ввода для другой команды.

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

Если вы хотите завершить функцию, для этого есть пара команд: return и exit. Команды выхода и возврата принимают числовой код: 0 означает успех, все остальное означает сбой. Команда return завершит работу функции, а команда exit завершит работу самой оболочки.

Коды выхода представляют собой целое число от 0 до 255 без знака. Если по какой-то причине вашему сценарию нужно более 255 различных способов потерпеть неудачу, то вам не повезло.

Перенаправление потоков

Вот основные моменты:

  1. | называется каналом, и вы используете его для отправки вывода другим командам. Например, мы можем попробовать hello | grep ‘Hello’. Эта конструкция отправит весь вывод команды hello в grep, который вернет строки, содержащие «Hello». Мое любимое повседневное использование каналов — history | grep «команда», когда я забыла точную команду, которую я набрала ранее, но я знаю, что в ней есть определенное слово.

  2. > с именем файла справа перенаправит вывод и запишет его в файл, а не на консоль. Файл будет полностью перезаписан. Например, logging_function> tmp_error.log. Если вам нравится Python, вы можете попробовать pip freeze> needs.txt.

  3. >> похоже на >, но дописывает в файл, а не перезаписывает его. Например, logging_function >> error.log.

  4. < обратно к > . Это перенаправление отправляет содержимое файла справа команде слева. Попробуйте grep foo <foo.txt. < is the reverse of. >

Каналы работают параллельно. Например, следующее будет работать только в течение одной секунды:

sleep 1 | sleep 1 | sleep 1 | sleep 1 | sleep 1

Участники канала не заставляют следующую команду в очереди ждать, пока они не будут полностью выполнены. Они обрабатывают и отправляют вывод по мере поступления.

Условия if

Ничто не иллюстрирует «маленькие инструменты» лучше, чем условие if в bash, которое на самом деле состоит из пяти ключевых слов:

if [ <expression> ]; then
<commands>
fi

Заметили, что условие заканчивается ключевым словом fi?

Так же и с оператором case … esac. Когда я узнала об этом, я понадеялась, что while будет завершено с помощью elihw, а until — с litnu. Но это, к сожалению, не так — эти операторы завершаются ключевым словом done.

[ это команда, а ] — это аргумент, который говорит прекратить принимать другие аргументы. If, else, elif и fi являются ключевыми словами.

Вот, например, ошибка:

/bin/sh: 1: [: true: unexpected operator

Вы можете подумать, что скрипт столкнулся с ошибочным [ и выдал синтаксическую ошибку. Это не так!

На самом деле происходит то, что команда [ получила неожиданный аргумент: true. Ошибка была на самом деле, потому что я использовала == вместо =, что было вычислено как true и неправильно при использовании оператора [.

Контроль выполнения

Я предпочитаю использовать if только там, где это действительно необходимо. Обычно я предпочитаю операторы bash: && и ||.

&& или || ставится после команды/функции. Если команда возвращает код 0, то команда справа от && будет выполнена, а команда справа от || нет:

$ will_return_0 && echo "I will print"
$ will_return_0 || echo "I will not print"
$ will_return_1 || echo "I will print"
$ will_return_1 && echo "I will not print"

Команды можно объединять в цепочки. Запустите следующие команды:

$ /bin/true && echo "I will print" || echo "I will not print"
$ /bin/false && echo "won't print" || echo "will print"

Но будьте внимательны! Порядок применения важен, нужно использовать вначале &&, а потом ||, но не наоборот. Если выполнить приведенную ниже команду:

/bin/false || echo "will print" && echo "won't print"

То в результате будет выведено обе строки, а не одна, как ожидалось.

Эти конструкции чуть сложнее читать, если вы не привыкли к языку командных сценариев. Условия if удобнее, если вам нужно сгруппировать несколько команд и нет смысла выносить эти команды в отдельную функцию.

Я также использую команду: test. Это то же самое, что и [ без вводящего в заблуждение синтаксиса. Менее знакомый синтаксис, мне кажется, лучше, потому что он сигнализирует читателю, что тот может не понимать, что именно происходит.

Переменные

Переменные в bash «дикие». Они работают так, как будто вы поместили их значение в скрипт и запустили его.

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

Такое поведение переменных может привести к некоторым ошибкам, поэтому вам никогда не следует принимать рискованный ввод данных от пользователя в сценарий оболочки (например из интернета). Если вы веб-разработчик и знаете, насколько опасен eval, то каждый сценарий оболочки — это гигантский оператор eval. Удаленное выполнение кода в любом количестве!

Для примера введите в терминале:

$ MY_VAR="echo stuff"
$ $MY_VAR

Вы должны увидеть выполнение команды, и вывод «stuff» на консоль. Такое поведение может сделать длинные скрипты глючными и непредсказуемыми. Например, попробуйте такой код:

$ HELLO="hello world"
$ test $HELLO = "hello world" && echo yes

Выполнение вызовет ошибку, потому что bash читает код как test hello world = “hello world”.

Именно поэтому одной из лучших практик считается всегда помещать переменные в двойные кавычки:

test "$HELLO" = "hello world" 
 [ "$HELLO" = "hello world" ]

Двойные кавычки в bash это не ограничители строк. Bash не обрабатывает строки так, как другие языки. Кавычки немного больше похожи на круглые скобки в других языках (но не на скобки bash — это подоболочки).

Одиночные и двойные кавычки различаются в bash. В большинстве случаев используются двойные кавычки. В чем разница? Двойные кавычки расширяют переменные, одинарные кавычки понимают их буквально. Например:

var=stuff
echo $var
echo "$var"
echo '$var'

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

test -z "$empty" && echo "variable is empty"

Также можно добавить параметр в сценарий, который покажет неустановленные переменные:

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

Область видимости

Понимание области видимости крайне важно, чтобы избежать ошибок.

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

Имя глобальной переменной должно быть ЗАГЛАВНЫМИ буквами. Чтобы сделать переменную доступной для всего терминала, используйте export VAR=”value”.

Верхний регистр говорит о том, что это глобальная переменная, а не о том, что это константа/неизменяемая переменная, как в других языках.

Команды

Моя самая нелюбимая вещь в bash — это запоминание маленьких загадочных команд; sed? cat? Что это значит? Имя, конечно, не скажет мне. Man зачастую трудны для понимания, и я, конечно, не вспомню, в каком порядке все должно идти.

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

Иногда поиск точной информации о том, что именно должна делать команда, напоминает поиск в пыльных архивах огромной библиотеки. К счастью, попадаются иногда супер-волшебники в Stack Overflow, которые не против поделиться своими с трудом заработанными знаниями.

Специальные переменные

Иногда вы сталкиваетесь со странными бессмысленными переменными, такими как $@ и $!. Вот их полный список.

Полезные переменные для написания скриптов и однострочников: $– и $*.

Они обе дают вам аргументы, с которыми работает команда/функция: $- — дает флаги, а $1-9 — ввод. Например:

Флаг — это -s, а example.com — это ввод.

Получая входные ключевые слова с $, важно использовать его так: ${2}, ${25} и так далее. Bash не поймет что-то вроде $42, если есть две цифры. Можно также сделать что-то вроде этого:

iterator=4
echo ${$iterator}

Подпроцессы и скобки

Если вы видите такую конструкцию:

То эти параметры вовсе не то, что вы думаете.

Скобки в bash на самом деле порождают вложенные процессы. Это означает, что они являются подпроцессами одного и того же сценария. По сути, это дочерние оболочки, которые получают весь родительский контекст (переменные, функции и так далее), но не могут ничего изменить в родительском процессе.

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

Во-первых, что они делают?

Давайте рассмотрим примеры:

!#/bin/bash
myVar="foo"
echo $myVar
(
    echo "Inside the sub-shell"
    echo $myVar
    myVar="bar"
    echo $myVar
)
echo "Back in the main shell now"
echo $myVar
foo
Inside the sub-shell
foo
bar
Back in the main shell now
foo

Обратите внимание, как переменная была изменена для контекста подпроцесса, но не за его пределами. Вот еще одна вещь, которая удобна для подпроцессов:

!#/bin/bash
echo "We start out in home"
pwd
(
   echo "In the subshell"  
   cd /tmp
   pwd
)
echo "Back in the main shell now"
pwd
We start out at root
/home/username
In the subshell
/tmp
Back in the main shell now
/home/username

Использование exit в подпроцессе приведет к выходу только из этого подпроцесса, а не из родительского сценария.

Круглые скобки — не единственный способ создания подпроцесса. Если вы поместите процесс в фоновый режим с помощью & или nohup, он также перейдет в подпроцесс.

Скрипты, которые вы запускаете с помощью ./, запускаются в своем собственном процессе, а не в подпроцессе вашего терминала, тогда как скрипты, которые вы запускаете с помощью команды source, запускаются так, как если бы вы вводили команды напрямую.

Вы можете ожидать, что функции будут выполняться в подпроцессах, но на самом деле это просто группировка команд.

Чтобы ваша функция запускалась в подпроцессе каждый раз, когда вы ее используете, вам нужно обернуть ее в скобки. Чтобы ваша функция возвращала определенный код завершения без запуска в подпроцессе и не вызывала выход из всего сценария, используйте return вместо exit.

Разделение на части

Иногда вам может потребоваться разбить ваш скрипт на файлы. Команда source поможет вам:

parent.sh:
!#/bin/bash
source /path/to/script.sh

В целом, это работает так, как будто вы добавили весь контент скрипта script.sh в скрипт parent.sh. Это значит, что если вы установите переменную в родительском скрипте, все скрипты, подключенные как source, будут иметь доступ к этой переменной.

Намного лучше использовать этот метод, как подключаемую библиотеку: импортировать вспомогательные функции, которые можно использовать в родительском скрипте.

Остерегайтесь кодов выхода и передачи значений в основной сценарий! Это не работает так, как вы думаете. Если в подключенном скрипте выполнение производится в основном процессе, то команда exit в подключенном скрипте завершит работу основного скрипта!

Рассказываем об IT-бизнесе, технологиях и цифровой трансформации

Подпишитесь в соцсетях или по email

Обработка ошибок

Я стараюсь группировать команды в функцию и обрабатывать ошибки, если функция не выполнилась:

my_function || handle_error

Перевод конспекта по bash, который содержит в себе выжимку самых основных возможностей Bourne again shell. Автор считает, что конспект будет полезен для каждого.

Доставайте ручки и чистые листы: здесь представлены основы основ по bash для начинающих!

Если вы работаете в ИТ, то как никто знаете о том, как ценно время. Оптимизация рабочего процесса — один из важнейших аспектов работы в ИТ. Так или иначе, наша работа (будь то верстка сайта, написание модулей, или тестирования приложений) требует повторения одних и тех же действий: быстрые скриншоты с загрузкой на сервер, обработка выделенного текста, конвертация файлов, парсинг данных и многое другое. Чтобы не делать лишних действий, а сконцентрироваться на идее и самой сути ее реализации, еще в 1978 году Стивен Борн разработал командную оболочку sh, которая впоследствии, в 1987 году была усовершенствована Брайаном Фоксом и переросла в то, что мы знаем сегодня как bash (Bourne again shell).

Вполне логично, что появляется вопрос: «Для чего мне нужно что-то, что написали почти полвека назад?» Так вот ответ на него прост: это «что-то» до сих пор является самым мощным инструментом автоматизации и, де-факто, стандартом для написания простых, но эффективных сценариев на всех unix-based системах. Именно поэтому знать общий синтаксис bash и уметь писать на нем — критический скилл для разработчика.

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

Оболочки и вызов сценариев

Пользовательская оболочка bash может работать в двух режимах — интерактивном и, соответственно, не интерактивном. Открыть оболочку в Ubuntu можно комбинацией клавиш Ctrl + Alt + F1, привычный графический интерфейс исчезнет, а перед вами откроется один из семи виртуальных терминалов, доступных в дистрибутиве Ubuntu.
Если оболочка выдает приглашение (что-то вроде того, которое можно увидеть ниже), то вы работаете в интерактивном режиме:

user@host:~$

Здесь можно вводить самые разнообразные unix-команды (как например: ls, grep, cd, mkdir, rm) и видеть результат их выполнения. Интерактивной эта оболочка называется потому, что она взаимодействует с пользователем напрямую. Окружение рабочего стола (графический интерфейс), в семействе систем Debian (к которым относится и Ubuntu), принято размещать в седьмом виртуальном терминале, для того чтобы вернуться к привычному окружение рабочего стола наберите комбинацию Ctrl + Alt + F7.

Конечно работать в виртуальных терминалах не слишком удобно, особенно, если нужно редактировать документ и одновременно выполнять какие-либо команды, поэтому в дальнейшем мы будем пользоваться встроенным в графический интерфейс эмулятором виртуального терминала, встроенным в Ubuntu. Открыть его можно комбинацией клавиш Ctrl + Alt + T, или Unity Dash, найдя его в списке программ.

В не интерактивном режиме оболочка читает команды из некоторого файла и последовательно выполняет их. Когда интерпретатор дойдет до конца файла, работа с оболочкой автоматически завершится. Запустить оболочку в не интерактивном режиме можно с помощью команд:

sh скрипт
bash скрипт

Где скрипт — это путь к файлу, содержащему команды для выполнения. Такой файл является обычным текстовым документом, который можно создать с помощью любого текстового документа. Впрочем, можно упростить вызов скрипта всего лишь сделав его исполняемым. Для этого необходимо предоставить соответствующие права доступа этому файлу с помощью команды chmod:
chmod +x скрипт

Кроме этого, в первой строке скрипта необходимо указать какая именно оболочка должна выполнять этот сценарий. Это можно сделать, разместив в начале соответствующее указание #! / Bin / sh (для оболочки sh) или #! / Bin / bash(соответственно для bash). После этого файл можно будет вызвать на выполнение обратившись к нему в терминале:

./скрипт

Комментарии

Сценарии могут содержать комментарии. Комментарии — это операторы, их можно размещать в сценарии оболочки, но который игнорируется при исполнении. Комментарии должны начинаются с символа # и продолжаются до символа новой строки.
Например:

#!/bin/bash
# Сценарий выведет имя пользователя
whoami

Переменные

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

Локальные переменные — это обычные переменные внутри одного сценария. Они не доступны другим программам и сценариям, которые запускаются с этой оболочки. Объявляются переменные с помощью символа = (обратите внимание на то, что перед и после = нет пробелов), а к их значениям обращаются с помощью символа $:

name="Петро Петрович"
echo $name # вывод значения
unset name # вывод переменной

Также можно создать локальную переменную внутри функции, которая будет доступна только в теле этой функции:

local локальная_переменная=значение

Переменные окружения — это переменные, которые доступны любым программам, запущенные с данной оболочки. Объявляются они так же как и локальные переменные, но с командой export :

export глобальная_переменная=значение

В bash есть много переменных окружения, которые достаточно часто встречаются в сценариях, например:

  • HOME — путь к домашнему каталогу пользователя;
  • PATH — список каталогов, в которых оболочка ищет исполняемые файлы;
  • PWD — путь к рабочему каталогу;
  • RANDOM — формирует целое случайное число;
  • HOSTNAME — имя компьютера, на котором выполняется оболочка;

Переменные оболочки — это переменные, которые устанавливаются оболочкой и необходимы ей для корректной работы. Эти переменные имеют имена порядкового номера ($ 1, $ 2, $ 3, …) и содержат аргументы, которые передавались сценарию при запуске, как:

./some_script.sh VAL1 VAL2 # внутри сценария $1='VAL1', $2='VAL2'

Переменным можно присваивать значения по умолчанию следующим образом:

: ${VAR:='значение по умолчанию'} # Если переменная VAR пустая, присвоить “значение по умолчанию”

Массивы и списки

В bash также есть возможность работы с массивами. При работе с ними часто пользуются переменной окружения IFS — разделителя полей для входных строк (IFS — Input Field Separator). По умолчанию IFS равен символу пробела, но может быть изменен для разбиения строки на элементы массива, например, запятыми. Обратите внимание, что для формирования переменных оболочки, которые доступны через $ 1, $ 2и т.д., используется именно переменная IFS, то есть введенная после имени скрипта строка аргументов будет разделена именно первым символом, который хранится в этой переменной.

Объявить массив можно следующим образом:

files[0]=Яблоко
files[1]=Груша
echo ${files[*]} # напечатает элементы массива без учета
IFS echo ${files[@]} # напечатает элементы массива с IFS в качестве разделителя

Получить доступ к элементу массива можно с помощью срезов: $ {arr: 0: 1}. Удалить первый элемент массива можно с помощью сдвига: shift arr. Добавить в элементы в массив: arr = ("$ {arr [@]}" "Item 1" "Item 2"). Проверка вхождения элемента в массив реализуется с помощью несколько более сложной конструкции:

if [[ ${arr[(r)some]} == some ]]; then # команды,если элемент входит
else # команды, если не входит
fi

В этом примере arr — некоторый массив, а some — это элемент, который мы проверяем на вхождение.

Результаты операций

Присвоить переменной результат работы команды или арифметических операций можно с помощью апострофов, или конструкции $ (выражение):

now=`data +%T`
# или
now=$(data +%T)
echo now # 19:08:26

Арифметические операции необходимо помещать в двойные скобки:

foo=$(( ((10 + 5*3) – 7) / 2 ))
echo $foo #> 9

С помощью фигурных скобок можно генерировать строки произвольного вида, или учитывать различные варианты написания слова:

echo beg{i,a,u}n #> begin began begun

Стоит вспомнить и о строгости кавычек в bash: одинарные кавычки — строгие, двойные — нестрогие. Это означает, что при подстановке переменных в строку с двойными кавычками, интерпретатор подставит соответствующее значение переменной. Одинарные кавычки выведут строку так, как вы её написали. Пример:

echo "Домашняя директория: $HOME" #> Домашняя директория: /home/user
echo 'Домашняя директория: $HOME' #> Домашняя директория: $HOME

Потоки

Файл с которого происходит чтение, называют стандартным потоком ввода, а тот в который происходит запись, соответственно — стандартным потоком вывода. В bash есть три стандартных потока:

0 stdin ввод
1 stdout вивод
2 stderr поток ошибок

Для перенаправления потоков используют основные операторы:

  • > — перенаправление потока вывода в файл (файл будет создан, или перезаписан)
  • >> — дописать поток вывода в конец файла;
  • < — перенаправляет данные из файла в поток ввода;
  • <<< — чтение данных из строки, вместо всего содержимого файла (работает для bash 3+)
  • 2> — перенаправляет поток ошибок в файл (файл будет создан, или перезаписан)
  • 2>> — дописать ошибки в конец файла;

Каналы

Стандартные потоки можно перенаправить не только в файлы, но и на вход других сценариев. Соединение потока вывода одной программы с потоком ввода другой называют каналом или пайпом (pipe) . Ниже приведен простой конвейер из трех команд: команда1 перенаправляет свой вывод на вход команды2, которая, в свою очередь, перенаправляет собственный вывод на вход команды3:

cmd1 | cmd2 | cmd3

Продолжение: Конспект по bash. Продолжение

Другие статьи по теме:

  • Команды bash, о которых вы, возможно, не знали
  • Быстрое изучение Bash: 30 легких команд для новичков

Вы когда-нибудь замечали, как супер-ботаник хакер в кино может легко проникнуть в самые безопасные банки и ограбить их все, просто набрав несколько команд, яростно уставившись в зеленый экран с черным фоном? Как человек последовательно получает доступ ко всем паролям и берет под контроль скрытые камеры, где бы он ни находился, всего несколькими нажатиями клавиш на клавиатуре. Ну, я не уверен, откуда у кинематографистов это взялось, но, наверное, это их способ сказать нам, что командная строка — это мощный инструмент, и без всех этих хакеров и ACCESS GRANTED!! До смешного..

Часто новички настолько привыкли работать с графическим интерфейсом GUI, что склонны игнорировать возможности интерфейса командной строки (CLI). Мышь очень удобна, когда нужно скопировать в папку около ста тысяч файлов, но что, если переименовать все эти тысячи файлов или разделить их по расширениям? Так как графические интерфейсы не программируемы, то переименование или разделение их с помощью командной строки заняло бы целую вечность, однако, мы могли бы быстро добиться этого за несколько строк кода.

Unix shell является довольно мощным инструментом для разработчиков всех видов. Эта статья призвана дать краткое введение в самые основы, начиная с операционной системы UNIX.

UNIX

Большинство современных операционных систем, за исключением WINDOWS, построены на базе UNIX. Среди них много дистрибутивов Linux, macOS, iOS, Android и др. Достаточно одного взгляда на схему развития операционных систем, основанных на UNIX, чтобы подчеркнуть важность UNIX, и именно по этой причине она стала широко использоваться на производстве. На самом деле, бэк-энд многих вычислительных систем, включая такие промышленные гиганты, как Facebook и Google, в значительной степени используют UNIX.

Shell

Shell — это интерфейс командной строки для запуска программ на компьютере. Пользователь набирает в строке запроса кучу команд, оболочка запускает программы для пользователя, а затем выводит результат. Команды могут быть либо введены непосредственно пользователем, либо прочитаны из файла, называемого shell-скриптом или shell-программой.

Shell. Какие бывают

UNIX-система обычно предлагает различные типы оболочек shell. Некоторые из них наиболее распространены:

Однако в этой статье мы ограничимся оболочкой Bash. Тем не менее, вам рекомендуется прочитать и попробовать другие оболочки, особенно zsh, так как уже в версии MacOS под названием Catalina zsh заменил оболочку bash. Так что будет хорошей идеей познакомиться с ним сейчас.

Terminal

Терминал — это программа, которая используется для взаимодействия с оболочкой. Это просто интерфейс к оболочке и к другим программам командной строки, которые запускаются внутри нее. Это похоже на то, как веб-браузер является интерфейсом для веб-сайтов. Вот как выглядит типичный терминал в Mac:

У Mac и Linux есть соответствующие версии терминала. Windows также имеет встроенную командную оболочку, но она основана на командной строке MS-DOS, а не на UNIX. Так что давайте посмотрим, как мы можем установить шелл и программу терминала в операционной системе Windows, которая работает так же, как и в системах Mac и Linux.

Установка терминала в WINDOWS

  • Подсистема Windows для Linux (WSL)

Это новая система совместимости с Linux в Windows 10. WSL позволяет разработчикам запускать GNU/Linux окружение — включая большинство инструментов командной строки, утилит и приложений — прямо под Windows, без изменений, без дополнительных виртуальных машин. Подробнее о его установке и функциях вы можете прочитать здесь.

  • Git Bash

Git Bash — это то, что мы будем использовать в этой статье. Скачайте Git на компьютер с Windows отсюда и установите его со всеми настройками по умолчанию. В конце концов, вы получите окно терминала, вроде того, что показано ниже.

Изучение терминала

Всякий раз, когда мы открываем окно терминала, мы видим наши последние учетные данные для входа и приглашение Shell. Строка shell появляется всякий раз, когда оболочка готова принять входные данные. Она может немного отличаться в зависимости от дистрибутива, но в основном она отображается как имяпользователя@имякомпьютера, за которым следует знак $.

Если вам не нужна вся эта информация, вы можете использовать PS1 для настройки командной строки.

Теперь терминал будет показывать только $ в строке. Однако это только временно и после перезапуска терминал вернется к своим первоначальным настройкам.

Приступим

Чтобы немного развлечься, давайте начнем с нескольких простых команд:

  • echo: выводит все, что вы набираете в командной строке шелла, аналогично Print на Python.

  • date: отображает текущие время и дату.

  • cal: отображает календарь на текущий месяц.

  • clear: очистит окно терминала, также можно использовать сочетание клавиш Ctrl-L.

Команда bash — наименьшая единица кода, которую bash может выполнить самостоятельно. Эти команды говорят bash, что нам нужно, чтобы он сделал. Обычно bash принимает от пользователя одну команду и возвращается к пользователю после ее выполнения.

Рабочая директория

pwd

pwd выводит содержимое рабочей директории и указывает на текущую рабочую директорию, то есть на директорию, которую оболочка просматривает в данный момент. Это также место по умолчанию, где команды оболочки будут искать файлы данных.
Директория похожа на папку, но в shell мы будем придерживаться наименования директория (каталог). Файловая иерархия UNIX имеет древовидную структуру. Чтобы добраться до определенной папки или файла, нам нужно пройти по определенным путям внутри этой древовидной структуры. Пути разделяют каждый узел вышеуказанной структуры с помощью символа слэш( / ).

Навигация по директориям

Для навигации и организации файлов используются команды ls и cd.

ls

ls обозначает список и показывает содержимое директории. ls обычно начинает с просмотра нашего домашнего каталога. Это означает, что если мы вызовем команду ls самостоятельно, то он всегда выведет содержимое текущего каталога, которым в моем случае является /Users/parul.

Параметры команды

Параметры и опции включают некоторые специальные функции при использовании команды ls.

  • ls <папка> : для просмотра содержимого определенной папки.
  • ls -a: Для перечисления всех скрытых файлов в папке
  • ls -l: Выводитболее длинный и подробный список файлов. ls -l также может быть использован с именем каталога для перечисления файлов этого конкретного каталога.
  • ls ~: tilde(~) — сокращение, обозначающее домашний каталог. Таким образом, независимо от того, в какой директории мы находимся, ls ~ всегда будет показывать содержимое домашнего каталога.

Немного о масках файлов

Оболочка также позволяет нам сопоставлять имена файлов с шаблонами, обозначенными звездочкой(*). Она служит подстановочным знаком для замены любого другого символа внутри заданного шаблона. Например, если мы введем *.txt, то это приведет к перечислению всех файлов с расширением .txt. Давайте попробуем перечислить все файлы с расширением .py в нашей папке Demo:

cd

cd, дословно, означает Change Directory (Изменить директорию) и изменяет активную директорию на указанный путь. После того, как мы используем cd в нужную директорию, можно воспользоваться командой ls, чтобы увидеть содержимое ее содержимое. Давайте посмотрим, как можно использовать эту команду:

  • cd … : Чтобы вернуться в родительский каталог.
  • cd : Для возврата в домашний каталог

Организация файлов

Существуют определенные команды, которые позволяют нам перемещать, удалять, создавать и копировать файлы из самой оболочки.

mkdir

mkdir означает Make directory и используется для создания новой директории или папки.

mv

mv означает Move и перемещает один или несколько файлов или каталогов из одного места в другое. Нам нужно указать, что мы хотим переместить, т.е. источник и куда мы хотим переместить их, т.е. место назначения.

Создадим в папке Demo новую директорию PythonFiles и переместим в нее все .py-файлы из папки Demo, используя две вышеприведенные команды.

touch

Команда touch используется для создания новых пустых файлов. Она также используется для изменения временных меток на существующих файлах и каталогах. Вот как мы можем создать файл под названием foo.txt в папке Demo.

rm

Команда rm означает «Удалить» и удаляет файлы или каталоги. По умолчанию она не удаляет каталоги, но если используется как rm -r * внутри каталога, то удаляется каждый каталог и файл внутри этого каталога.
Теперь удалим ранее созданный файл foo.txt.

rmdir

rmdir означает «удалить каталог» и используется для удаления пустых каталогов из файловой системы. Давайте удалим папку PythonFiles, которую мы создали некоторое время назад.

Обратите внимание, что ../ обозначает родительский каталог.

Просмотр файлов

Это еще один нюанс использования оболочки shell, который очень полезен. Существуют команды, которые помогают нам просматривать содержимое файла, чтобы мы могли ими манипулировать.

cat

Команда cat читает файл и выводит его содержимое. Она может читать любое количество файлов, как следует из ее наименования. В нашей папке Demo есть несколько текстовых файлов, давайте используем cat, чтобы просмотреть их содержимое.

Чтобы просмотреть более одного файла, укажите оба имени файлов после команды cat:

$ cat Names.txt fruits.txt

less

Команда cat отображает содержимое файла на экране. Это нормально, когда содержимого мало, но это становится проблемой, когда файл большой. Как видно из примера ниже, команда выводит все на терминал с очень высокой скоростью, и мы не можем разобраться во всем содержимом файла. К счастью, есть команда под названием «Меньше», которая позволяет нам просматривать содержимое по одному экрану за раз.

$ less babynames.txt

Существуют определенные варианты с меньшим количеством используемых опций:

Пробел: перейти к следующему экрану
b: перейти к предыдущему экрану
/: для поиска конкретного слова
q: выйти

man

Команда man отображает страницы мануалов, которые являются руководством пользователя, встроенным по умолчанию во многие Linux и большинство Unix операционных систем.

man bash : Чтобы отобразить всю инструкцию bash

man <ключевое слово>, например man ls выдает информацию о команде ls.

Каналы и фильтры

Оператор pipe ‘|’ (вертикальная полоса) — это способ отправки вывода одной команды в качестве входной для другой команды.

command1 | command2

Когда команда посылает свой выход в канал, принимающей стороной для этого выхода является другая команда, а не файл. На рисунке ниже показано, как команда wc подсчитывает содержимое файла, отображенного командой cat.

wc — это команда, которая принимает данные на входе и каким-то образом преобразует их вывод. Такие команды называются фильтрами и помещаются после Unix каналов.

Фильтры

Теперь давайте посмотрим на некоторые часто используемые команды фильтров. Мы будем работать с файлом под названием babynames.txt, который содержит около 1000 имен детей, и с файлом fruits.txt, который содержит имена нескольких фруктов.

  • grep или глобальное регулярное выражение ищет строки с заданной строкой или ищет шаблон в заданном входном потоке и выводит результат. Следующая команда прочитает все файлы и выведет все строки, содержащие либо слово ‘Tom’.

Но получился большой список, и мы не можем разобраться во всех этих данных, только что выведенных в терминале. Давайте посмотрим, как мы можем использовать оператор pipe, чтобы разобраться в этом.

  • Фильтр wc — это сокращение от количества слов (word count). Он читает список файлов и генерирует одну или несколько следующих статистик: количество новых строк, количество слов и количество байтов. Введем в wc вывод вышеприведенной команды grep для подсчета количества строк, содержащих слово ‘Tom’.

  • Фильтр sort сортирует строки в алфавитном или цифровом порядке.

Команда cat сначала читает содержимое файла fruits.txt, а затем сортирует его.

  • Фильтр uniq означает «уникальный» и дает нам количество уникальных строк во входном потоке.

Важно отметить, что uniq не может обнаружить дубликаты записей, если они не находятся рядом. Поэтому мы использовали сортировку файла перед использованием команды сортировки. В качестве альтернативы можно также использовать команду sort -u вместо uniq.

Каналы очень удобны для выполнения некоторых сложных задач, так как несколько команд могут быть объединены в один канал вывода.

Что изучить еще по теме?

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

  • Командная строка Linux пятое интернет-издание William Shotts
  • Bash — Руководство для начинающих
  • The Bash Academy

Понравилась статья? Поделить с друзьями:
  • Асинак таблетки инструкция по применению цена
  • Мануал у органа 10 букв сканворд первая буква к
  • Управление персоналом или руководство кадрами
  • Инструкция по охране труда слесаря сантехника 2022 по новым правилам
  • Каметон аэрозоль инструкция по применению цена детям