Ликбез по Linux

Изучаем Bash. Часть 1

Сегодня начнём разбирать возможности bash. Так как этот вопрос довольно объёмный, его придётся разбить на несколько частей. Итак, пойдём от простого к сложному. Кстати, есть очень большая вероятность, что информация, усвоенная при изучении bash, пригодится при работе с другими командными интерпретаторами.


Стандартный поток ввода и вывода

Эти довольно важные понятия означают всего-навсего то, откуда по умолчанию читает программа данные (stdin) и куда выводит результаты своей работы (stdout). Также существует стандартный поток вывода ошибок (stderr). Обычно это экран (точнее, терминал пользователя) + клавиатура. Для чего это надо знать? А дело в том, что все эти потоки можно перенаправлять. Чаще всего для ввода/вывода используют файлы.

Например, так можно создать файл, содержащий список фалов в указанной директории.

$ ls -l > ~/file_with_files

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

$ ls -l >> ~/file_with_files

Также, при выполнении команды можно разделять потоки.

  • stdin имеет номер 0
  • stdout имеет номер 1
  • stderr имеет номер 2

То есть можно выводить ошибки в отдельный файл, причём обычные сообщения будут при этом отображаться как обычно. Для этого нужно перед ">" поставить число 2 (номер потока, аналогично для stdin, stdout). Например, так

$ find / -name .bashrc 2> ~/finderrors.txt

Кроме того, существует такое устройство, как /dev/null, на который можно также перенаправлять вывод. При этом ничего из направленного не будет нигде отображаться.

$ find / -name asdf 2 > /dev/null

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

$ cat ~/finderrors.txt > wc -w

Если вам нужно написать скрипт, в котором какая-то программа требует ввода, то можно направить в неё содержимое файла

$ wc -w < ~/finderrors.txt

Примечание. ">" без указания номера потока трактуется как "1 >". То есть выводиться будет только stdin.


Конвейеры

Наверняка вы видели команды следующего вида:

$ cat /etc/bash.bashrc | more

В результате её работы будет приостановлен вывод при заполнении экрана. Так вот, "|" и есть этот самый конвейер. Говоря по-умному, это канал, в который один процесс может только писать, а другой - только читать. Выборка и помещение в такой конвейер идёт по принципу FIFO (First In - First Out). Также этот принцип называется очередь, что очень просто и точно характеризует его работу. Конвейеры используются для того, чтобы скомбинировать работу нескольких маленьких программ.

Разберём работу следующей команды:

$ cat myfile | grep Linux | we -1

Сначала cat myfile выводит содержимое файла myfile, затем grep Linux считывает вывод и выделяет только строки, содержащие слово Linux. Потом wc -l считает количество строк. В результате мы получим количество строк, содержащих слово Linux.

Очень удобно использовать утилиту xargs вместе с "|". xargs читает элементы вывода stdin, разделённые пробелами, и выполняет программу, передав их ей один или несколько раз.

Например:

$ find /tmp -name core -type f -print | xargs /bin/rm -f

Эта команда находит файлы с именем core в директории /tmp и удаляет их.


Специальные символы

В отличие от ОС Windows, имена файлов в Linux могут содержать почти любые символы (например, имя файла example*of/file вполне реально). Но некоторые знаки bash использует как служебные. И для корректной работы необходимо эти символы экранировать. Это можно сделать несколькими способами.

Можно взять выражение в кавычки. Например:

$ cp "example*of/file" ~

Также можно использовать одиночные кавычки

$ cp 'example*of/file' ~

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

Но самым универсальным является С-подобный способ отмены специальных символов. Для этого достаточно перед символом поставить "\" (без кавычек). Например, наша команда будет выглядеть следующим образом:

$ cp example\*of\/file ~


Выполнение команд

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

Если нужно последовательно выполнить несколько команд, то их следует разделить символом ";". Например, следующая последовательность скомпилирует файл (а компиляция - долгий процесс, можно в это время поспать!), затем выключит компьютер.

$ make ; sudo shutdown -h now

Если же нужно выполнить программу в фоновом режиме (то есть вернуть управление пользователю сразу после запуска, это бывает удобно при запуске графических приложений), то необходимо после команды поставить символ "&". Например:

$ sudo synaptic &

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

А что же делать, если нам нужно выполнить команду только в том случае, если операция успешно завершится. Например, есть следующая задача.

Нужно скомпилировать файл. Для этого нужно выполнить configure, make, sudo make install. Причём выполнять нужно только в том случае, если предыдущая команда закончилась успешно.

В таких случаях применяется последовательность "&&". Оператор, стоящий после "&&", выполняется только в том случае, если предыдущая завершилась успешно. То есть у нас это будет выглядеть так:

$ ./configure && make && sudo make install

Если же нужно выполнить только в том случае, если программа завершится с ошибкой, то используем "||". Например, усложним задачу. Нужно будет при ошибке записать её в файл, а затем, независимо от окончания, выключить компьютер.

$ ./configure && make && make install || echo fail > ~/errorfile ; sudo shutdown -h now


Шаблоны имён файлов

Проще всего их перечислить в табличке. Стоит помнить, что шаблоны можно комбинировать в одной команде.

* - любая последовательность символов, в том числе и пустая;

? - любой одиночный символ;

{a,b,c,d} - любой из символов, перечисленных в скобках;

[0-6,a-d] - любой символ из указанных интервалов;

[^0-6] - любой символ, не входящий в указанные интервалы.

Проще всего их разбирать на примере.

Допустим, у нас есть папка, содержащая следующие файлы.

Glava01, Glava02, Glava03, Glava04, Glava05, Glava15, Glava17.

Применим шаблон Glava0* и получим список Glava01, Glava02, Glava03, Glava04, Glava05.

Применим шаблон Glava?5 и получим список Glava05, Glava15.

Применим шаблон Glava?{4,5} и получим список Glava04, Glava05, Glava15.

Применим шаблон Glava0[1-3] и получим список Glava01, Glava02, Glava03.


Выполнение арифметических выражений

Да, bash и такое умеет. Для этого есть две формы:

первая: $[выражение]

вторая: $((выражение))

Например:

$ echo $[2+2*2]

В результате выполнения выведется число 6. Если выражение некорректно, то bash выдаст сообщение об ошибке.


Подстановка команд

Подстановка команд является очень мощным средством bash. Смысл в том, что записанная команда меняется на результат её выполнения. Существуют две формы записи: $(команда) и 'команда' (в этом случае используются не одиночные кавычки, а символы, получающиеся при комбинации SHIFT+~). Например, вот яркий пример, который используется в Debian при установке заголовочных пакетов текущего ядра:

# apt-get install linux-headers-'uname -r'

Команда uname -r при своём выполнении выдаёт версию используемого ядра. То есть при выполнении у меня она меняется на

# apt-get install linux-headers-2.6.25-2-686

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


Фильтры

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

cat - на стандартный вывод (то есть на экран) выводится содержимое указанного файла (или нескольких файлов, если их имена последовательно задать в качестве аргументов команды);

grep, fgrep, egrep - ищут во входном файле или данных со стандартного ввода строки, содержащие указанный шаблон, и выдают их на стандартный вывод;

tr - заменяет во входном потоке все встречающиеся символы, перечисленные в заданном перечне, на соответствующие символы из второго заданного перечня;

comm - сравнивает два файла по строкам и выдаёт на стандартный вывод три колонки: в первой - строки, которые встречаются только в 1-м файле, во второй - строки, которые встречаются только во 2-м файле, и в третьей - строки, имеющиеся в обоих файлах;

pr - форматирует для печати текстовый файл или содержимое стандартного ввода;

sed - строковый редактор, использующийся для выполнения некоторых преобразований над входным потоком данных (берётся из файла или со стандартного ввода);

more и less - выводят содержимое файла на экран отдельными страницами размером как раз в целый экран;

wc - подсчитывает количество слов, строк или байт в потоке.

Например,

$ grep CONFIG_XEN . -Rl | xargs -i sed -i -e 's/CONFIG_XEN/CONFIG_LUPO/g' {}

ищет файлы в текущей папке, содержащие строку "CONFIG_XEN", и меняет её на "CONFIG_LUPO" во всех найденных файлах.

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

Антон ЛИПАРИН,
oni-ddr.livejournal.com

Версия для печатиВерсия для печати

Номер: 

39 за 2008 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Инкогнито
[code]В отличие от ОС Windows, имена файлов в Linux могут содержать почти любые символы (например, имя файла example*of/file вполне реально).[/code]

Не реально. Символ / не может использоваться в имени файла, а все остальные, пожалуй, могут.

Аватар пользователя mike
Не реально, подтверждаю.
Аватар пользователя Oni
Действительно, не проверил. Извиняюсь за ошибку.
Аватар пользователя mike
2Oni. Вот поставил себе 2 бесплатных пакета: partimage и mondo, чтобы имиджить Линукс. 1-ый - фтопку, 2-ой ИМХО заслуживает статьи.
Аватар пользователя интернетчик
>>...mondo

Неблагозвучно :)

Аватар пользователя mike
>Неблагозвучно

The Teenage Mutant Ninja Turtles described cool things as ’mondo’. Hugo Rabson wasn’t sure what to call this

project. ’Faust’ was one idea he had, partly as a dig at his former boss who practically owned him because of his legal status at the time. In the end, he chose something short and distinctive. Но не для славянского уха. Хьюго Рэбсон - инициатор разработки. 1-ый релиз был в 2000г. Вещь неплохая, хорошо документирована и постоянно освежается. Собирать из тарболлов не надо, стаёт через apt-get!

Аватар пользователя Oni
>>mondo

Надо будет посмотреть

Аватар пользователя mike
mondo/mindi хорошо работает с "Федорой", но плохо с "Убунтой". Для "Убунты" я перешёл на QuickStart. Вот только что клонировал "Убунту" на HDD 6GB c HDD 80 GB, правда, UUID менял вручную, узнав через sudo vol_id. Плюс QuickStart'а - позволяет ставить драйвера/кодеки для видео и музыки. Бесплатен, но код закрыт.