Описание: Кандидат BSDA должен свободно пользоваться оболочками sh(1), csh(1) или tcsh(1). Кандидат должен уметь изменять поведение обеих оболочек временно или постоянно, включая: предотвращать уничтожение существующих файлов, использовать историю команд, определять псевдонимы команд для экономии времени в командной строке. Кандидат должен знать как временно отменить псевдоним.
Практика: 
      sh(1), csh(1) и tcsh(1), включая !,
      !!, $, 0,
      h, t, r,
      p, \.
    
В системах BSD поставляется две оболочки, наличие которых требуется стандартом POSIX: sh(1) и csh(1). Первая традичионно используется для написания сценариев. Вторая больше приспособлена для работы в интерактивном режиме. Конечно ничто не мешает вам установить у себя bash(1) или другую, более или менее «продвинутую» оболочку, однако в нашем курсе мы изучаем только штатные средства BSD, и на то есть свои основания (см. Раздел 7.7.2, «Почему sh(1)?»).
Поскольку данный раздел посвящён интерактивной работе с оболочками, мы будем описывать в нём почти исключительно csh(1). Полное описание данной оболочки, на русском языке, доступно здесь: [url://csh-1998].
С другой стороны, я отдаю себе полный отчёт в том, насколько популярна оболочка bash(1) среди системных администраторов, поэтому иногда буду делать реверансы в её сторону в стиле «... а в bash(1) тоже есть подобная функция, она делатся так: ...». Кроме того, в случае если некая упоминаемая возможность есть и в bash(1) и в sh(1) я буду делать реверансы в пользу sh(1), хотя последний крайне неудачен с точки зрения интерактивной работы.
![]()  | Важно | 
|---|---|
csh(1) по умолчанию является оболочкой
        пользователя root. Никогда не меняйте её на
        bash(1) или любую другую оболочку из иерархии
        /usr/local! От пользователя root требуются
        некоторые действия в критические моменты жизнедеятельности системы,
        когда иерархия /usr несмонтирована. Поэтому
        уметь работать в csh(1) может быть жизненно
        важно.
       | 
        Для этой цели в оболочках существует режим
        «noclobber». В csh(1) он включается
        путём задания переменной окружения noclobber.
      
%touch test%set noclobber=1%echo hello > test test: Файл существует.%unset noclobber%echo hello > test
        В sh(1) этот режим можно включить используя
        аргумент командной строки -C. Таким образом, можно использовать
        shebang #!/bin/sh -C.
      
Существует ряд отличий между оболочками с точки зрения языка. Язык csh(1) сделан более C-подобным. Изменения довольно глубоки, в частности csh(1) трактует 1 как истину, а 0 как ложь, в отличие от sh(1), поэтому он преобразует на лету коды возврата программ 0 к 1, а всё, что больше 0 к нулю. В csh(1) иной синтаксис написания циклов и других конструкций, больше типов данных. Так в csh(1) поддерживаются массивы (массивы поддерживаются и в bash(1)).
csh(1) поддерживает работу с историей команд и completion. (К стыду своему не знаю как это будет по-русски, имеется ввиду явление когда имена файлов дописываются при нажатии клавиши <TAB>). Ни то, ни другое не поддерживается в sh(1) (но поддерживается в bash(1)).
Если в переменной в csh(1) содержится имя файла, то с ним можно работать используя различные модификаторы:
%set name=/home/emin/BSDCert/BSDCert.xml%echo $name /home/emin/BSDCert/BSDCert.xml%echo $name:h/home/emin/BSDCert
%echo $name:t BSDCert.xml%echo $name:e xml%echo $name:h:h/home/emin
%set names=(/home/emin/BSDCert/*)![]()
%echo $names /home/emin/BSDCert/BSDCert.xml /home/emin/BSDCert/Makefile /home/emin/BSDCert/de fault.css /home/emin/BSDCert/index.shtml /home/emin/BSDCert/macro.vim /home/emin /BSDCert/single.xsl /home/emin/BSDCert/split.xsl%echo $names[1]/home/emin/BSDCert/BSDCert.xml
%echo $names[1]:h /home/emin/BSDCert%echo $names[1]:t BSDCert.xml%echo $names:h/home/emin/BSDCert /home/emin/BSDCert/Makefile /home/emin/BSDCert/default.css /h ome/emin/BSDCert/index.shtml /home/emin/BSDCert/macro.vim /home/emin/BSDCert/sin gle.xsl /home/emin/BSDCert/split.xsl
%echo $names:gh/home/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert /hom e/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert
%echo $names:gt BSDCert.xml Makefile default.css index.shtml macro.vim single.xsl split.xsl%echo $names:ge xml css shtml vim xsl xsl
Похожие фокусы возможны, впрочем, и в sh(1) (правда в нём нет массивов):
$name=/home/emin/BSDCert/BSDCert.xml$echo $name /home/emin/BSDCert/BSDCert.xml$echo ${name%/*} /home/emin/BSDCert$echo ${name##*/} BSDCert.xml$echo ${name##*.} xml
Впрочем, последний пример явно потерпит фиаско, если в имени файла расширения не будет, и, что ещё хуже, если в имени файла его не будет, а в имени каталога, в котором он находится, оно будет.
Таблица 7.11. Модификаторы переменных в csh(1)
| Модификатор | Описание | 
|---|---|
| h | Удалить имя файла, сохранив компоненты пути (то есть удалить в слове текст справа до ближайшего символа /). От слова head. | 
| gh | Применить модификатор h глобально ко всем элементам массива | 
| r | Удалить расширение файла, указанное через точку, и саму точку | 
| gr | Применить модификатор r глобально ко всем элементам массива | 
| e | Удалить имя файла вместе с точкой, сохранив расширение имени | 
| ge | Применить модификатор e глобально ко всем элементам массива | 
| t | Сохранить имя файла, удалив компоненты пути (то есть удалить текст слева от самого правого символа / и сам этот символ). От слова «tail». | 
| gt | Применить модификатор t глобально ко всем элементам массива | 
| q | Запретить дальнейшую модификацию слова. Слово заключается в кавычки | 
| x | Разбить на слова по разделителям и запретить дальнейшую модификацию. Результат заключается в кавычки. | 
Для просмотра истории команд служит встроенная команда history:
% history
   1  14:27   set name=/home/emin/BSDCert/BSDCert.xml
   2  14:28   echo $name
   3  14:28   echo $name:h
   4  14:28   echo $name:t
   5  14:28   echo $name:e
   6  14:28   echo $name:h:h
   7  14:29   set names= ( /home/emin/BSDCert/* )
   8  14:29   echo $names[1]
   9  14:29   echo $names[1]:h
  10  14:30   echo $names[1]:t
  11  14:30   echo $names:h
  12  14:30   echo $names:gh
  13  14:30   echo $names:gt
  14  14:30   echo $names:ge
        
        При помощи символа ! можно выполнить
        некоторые действия из истории, например:
      
%!1set name=/home/emin/BSDCert/BSDCert.xml
%!7 set names= ( /home/emin/BSDCert/* )%!?his?history 1 14:27 set name=/home/emin/BSDCert/BSDCert.xml 2 14:28 echo $name 3 14:28 echo $name:h 4 14:28 echo $name:t 5 14:28 echo $name:e 6 14:28 echo $name:h:h 7 14:29 set names= ( /home/emin/BSDCert/* ) 8 14:29 echo $names[1] 9 14:29 echo $names[1]:h 10 14:30 echo $names[1]:t 11 14:30 echo $names:h 12 14:30 echo $names:gh 13 14:30 echo $names:gt 14 14:30 echo $names:ge 15 15:30 history 16 15:31 set name=/home/emin/BSDCert/BSDCert.xml 17 15:31 set names= ( /home/emin/BSDCert/* ) 18 15:31 history
%-2set names= ( /home/emin/BSDCert/* )
%!!set names= ( /home/emin/BSDCert/* )
%!eecho $names:ge xml css shtml vim xsl xsl
Разберём чуть более сложный пример:
%touch abc cba%cat !!*cat abc cba
%echo 'aaa\?bbb\?ccc' > abc%echo 'aaa\?bcb\?ccc'> cba%diff !t*diff abc cba 2c2 < bbb --- > bcb
%echo !t:0echo touch touch
%echo !t:1 !t:2echo abc cba abc cba
%echo !?ab?%echo abc abc
%echo !t^ !t$echo abc cba abc cba
        Разрешается не ставить двоеточие перед знаками
        *, ^, $,
        - и %
      
В работе с историей команд можно использовать модификаторы. Некоторые модификаторы были рассмотрены выше, есть и специфические модификаторы, которые применяются только здесь:
p&s/pattern/subst/Пусть после выполнения команды history на экран дисплея выведено:
% history
  1  cat /home/ivanov/file1.c
  2  cc pa1.c pa2.c pa3.c pa4.c >& errors &
  ...
        Тогда следующие команды приведут к следующим действиям:
!1:0  !1^:t:rcat. Затем первое слово первой
            строки (/home/ivanov/file1.c),
            к которому будет последовательно применено два
            модификатора: :t и :r, в
            результате останется file1.
            Итого, получаем команду cat
              file1.
          !1:0  !1^:h/documentcat
              /home/ivanov/document.
          !1:0  !1^:h:s?ivanov?sidorov?/documentcat /home/sidorov/document!1:0  !1^:h:s?ivanov?sidorov?/doc !1^:&:pcat /home/sidorov/doc
              /home/sidorov/file1.c. Здесь модификатор
            & заставляет повторить предыдущую
            замену, а модификатор :p заставляет
            просто напечатать результат на экране, вместо того, чтобы
            выполнить действие.
          !1:0 !2:1-4:gs?pa?ff?:pg) делается замена
            pa на ff, результат печатается:
            cat ff1.c ff2.c ff3.c ff4.cСуществует способ редактирования последней командной строки:
%echo abc cba abc cba%^abc^cba^ echo cba cba cba cba
Представьте себе, что у вас определён следующий псевдоним:
% alias sp "sort \!* | print"
        
        Теперь команды sp one two и sort one two | print тождественны, так
        как в !* будут подставлены аргументы, с
        которыми вызвана команда sp.
      
