Основы использования командной строки

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

Мы уже говорили, что программа когда запускается, то ей сразу передаётся три файловых дескрипотра --- стандартный ввод (0), стандартный вывод (1) и стандартный поток ошибок (2). Открытием этих файлов занимается ОС, прграмма запущенная уже получает их открытыми. Её дело --- читать из 0, выводить 1 и ошибаться в 2. Не её дело открывать их и закрывать. Это очень удобно, потому что по умолчанию все три потока ассоциируются с терминалом. Нпример, прграмма cat довольно бессмысленна сама по себе --- читает из stdin и выводит в stdout.

$ cat  
Hello                       
Hello                 

Но если программа, которая её запускает, подсунет ей другие дескрипторы, то оно так и будет, средствами шелла это делается при помощи <, > и >>. В первом случае перенаправление на стандартного потока ввода, во втором и третьем --- стандартного потока вывода в файл.

$ cat >> File
Hello                       
$ cat < File
Hello                       
$ cat >> File
I love you                  
$ cat < File
Hello                       
I love you                  
$ cat > File
Hello?                      
$ cat < File
Hello?                      
$ cat < File > .FileFile
$ cat .FileFile
Hello?                      

Для перенаправления stderr надо использовать 2> filename. (у утилиты cat нету ключа --l, и она выдаёт диагностику в стандартный поток ошибок).

$ cat --l < File > .FileFileFile 2>Error
$ cat Error
cat: нераспознанный ключ `--l'

При этом при первом вызове cat ничего на экран не попало, всё ушло в файлы.

Ещё более интересным и мнгообещающим является перенаправление stdout однй программы на stdin другой. При этом происходит такая штука: создаётся безымянный pipe, который в ФС отсутствует, но позволяет передавать данные между процессами.

Команда cal выводит календарь на месяц, раскрашивая сегодняшний день, поскольку она определяет, что stdout --- терминал. cal | cat организует перенаправление при помощи безымянного канала, при этом cal определяет, что stdout не терминал и ничего не раскрашивает.

$ cal | cat
     Июль 2008              
Вс Пн Вт Ср Чт Пт Сб        
       1  2  3  4  5        
 6  7  8  9 10 11 12        
13 14 15 16 17 18 19        
20 21 22 23 24 25 26        
27 28 29 30 31     

Программа wc выводит количество символов-слов-переводов строк.

$ cal | wc
      8      40     186 

Можно делать длинные конфейеры: cal | tac | tac (утилита tac выводит поступившие ей строки в обратном порядке, тем самым, если применить её два раза, ничего не произойдёт):

$ cal | tac | tac
     Июль 2008              
Вс Пн Вт Ср Чт Пт Сб        
       1  2  3  4  5        
 6  7  8  9 10 11 12        
13 14 15 16 17 18 19        
20 21 22 23 24 25 26        
27 28 29 30 31           

cal | head -2 | tail -1 (утилита head выводит заданное количество первых строк ввода, tail --- последних. Комбинируя эти утилиты, можно получить произвольный срез файла по строкам):

$ cal | head -2 | tail -1
Вс Пн Вт Ср Чт Пт Сб 

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

Всякие способы работы с шеллом.

Шелл --- штука триединая. Тот интерпретатор, с которым мы работаем, выполняет три функции:

Что касается второй: мы немного поработали с фалами, у нас есть механизм передачи информации от одного процесса другому. Если мы говорим, что шелл --- ЯП, то надо бы иметь переменные. Мы можем присвоить переменной значение. Обратите внимание на две вещи: переменные все строковые. Почему --- потому что вычислительные задачи лучше решать на языке, пригодном для вычислений, и использовать подобные написанные программы, интегрируя их с другими шеллом. Имя переменной инициализируется в первом присваивании, значение переменной --- $имя.

$ VAR="Value Value"
$ echo $VAR
Value Value

Это в общем показало нам шелл как некий извращённый язык программирования, если бы не одна особенность.

Текущий каталог входит в окружение процесса, то есть любой процесс в системе имеет в своём контексте тот каталог, который является текущим. На самом деле, в этот контекст входит не только текущий каталог. В окружение входят дескрипторы всех открытых файлов, идентификатор пользователя, идентификатор группы, и куча других переменных. Но у них какое-то значимое содержимое, каждая что-то значит. Более того, при форке процесса наследуется окружение. Важно, что переменная HOME была определена при логине и все процессы пользователя получают её в наследие от шелла, который запускается при логине (login shell). Кроме этго, есть много других переменных --- пользователь, имя шелла... Очень важная переменная PATH содержит список каталогов, в которых шелл ищет исполнимые файлы, если данное имя команды не является встроенным.

$ echo $PATH
/home/george/bin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/usr/games

В отличие от DOS, текущий каталог не используется при поиске программы.

Подстановки.

Чтобы дать пример того, насколько мощным интегратором является шелл, рассмотрим ещё одну вещь. Обратите внимание на то, каким образом переменной присваивается значение с пробелом. Закавычивание для параметра с пробелами сохраняет его в том виде, в котором он написан внутри кавычек. Если без кавычек, то будет иначе.

$ echo "$VAR"
Value                   Value
$ echo $VAR
Value Value

Генерация список файлов по шаблону (FNG, FileName Generation). Что это такое? Когда вы хотите совершить групповую операцию над файлами, то для задания групп используются специальные символы: * --- любое количество символов, ? --- один символ, [abc] или [a-z] --- символ из диапазона, [^a-z] --- символ не из диапазона.

Например, echo F*.

$ echo F*
FFFFF FFFile1 FFFile2 File File1 File2 File3 File4 File45

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

$ echo File??
File45                      
$ echo File[2-4]
File2 File3 File4           
$ echo File[^2-4]
File1                       
$ echo File[2-4F*]
File2 File3 File4           
$ echo File[2-4F]*
File2 File3 File4 File45    

Кто превратил F* в список файлов? Шелл. Когда шелл видит спецсимвол, то он применяет шаблон к именам файлов. Какие вещи не стоит забывать при использовании FNG: этим занимается шелл, и прграмма ничего об этом не знает. Второе --- файлы с точки не включаются в FNG по умолчанию. При этом .* включит файлы . и .., что не всегда хорошо. {{{$ echo .* . .. .FileFile .FileFileFile }}} Общего решения для этого нет, но в частных случаях можно попробовать исключения (.[^.]* ..?*):

$ echo .[^.]*
.FileFile .FileFileFile


Сведения о ресурсах

Готовность (%)

Продолжительность (ак. ч.)

Подготовка (календ. ч.)

Полный текст (раб. д.)

Предварительные знания

Level

Maintainer

Start date

End date

19

1

1

1

1

MaximByshevskiKonopko, Allena, VsevolodKrishchenko


CategoryLectures CategoryPspo CategoryMpgu CategoryUneex