Искусство программирования на языке сценариев командной оболочки - страница 9

стр.

, cat и т.п.), которые выводят результаты своей работы в stdout.

bash$ echo "whatever" | cat -

whatever


В случае, когда ожидается имя файла, тогда "-" перенаправляет вывод на stdout (вспомните пример с tar cf) или принимает ввод с stdin.

bash$ file

Usage: file [-bciknvzL] [-f namefile] [-m magicfiles] file...

Сама по себе команда file без параметров завершается с сообщением об ошибке.

Добавим символ "-" и получим более полезный результат. Это заставит командный интерпретатор ожидать ввода от пользователя.

bash$ file -

abc

standard input: ASCII text


bash$ file -

#!/bin/bash

standard input: Bourne-Again shell script text executable

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

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

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

grep Linux file1 | diff file2 -

И наконец пример использования служебного символа "-" с командой tar.

Пример 3-4. Резервное архивирование всех файлов, которые были изменены в течение последних суток

#!/bin/bash


# Резервное архивирование (backup) всех файлов в текущем каталоге,

# которые были изменены в течение последних 24 часов

#+ в тарболл (tarball) (.tar.gz - файл).


BACKUPFILE=backup

archive=${1:-$BACKUPFILE}

# На случай, если имя архива в командной строке не задано,

#+ т.е. по-умолчанию имя архива -- "backup.tar.gz"


tar cvf - `find . -mtime -1 -type f -print` > $archive.tar

gzip $archive.tar

echo "Каталог $PWD заархивирован в файл \"$archive.tar.gz\"."


# Stephane Chazelas заметил, что вышеприведенный код будет "падать"

#+ если будет найдено слишком много файлов

#+ или если имена файлов будут содержать символы пробела.


# Им предложен альтернативный код:

# -------------------------------------------------------------------

# find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"

# используется версия GNU утилиты "find".


# find . -mtime -1 -type f -exec tar rvf "$archive.tar" '{}' \;

# более универсальный вариант, хотя и более медленный,

# зато может использоваться в других версиях UNIX.

# -------------------------------------------------------------------


exit 0

Могут возникнуть конфликтные ситуации между опреатором перенаправления "-" и именами файлов, начинающимися с символа "-". Поэтому сценарий должен проверять имена файлов и предаварять их префиксом пути, например, ./-FILENAME, $PWD/-FILENAME или $PATHNAME/-FILENAME.

Если значение переменной начинается с символа "-", то это тоже может быть причиной появления ошибок.

var="-n"

echo $var

# В данном случае команда приобретет вид "echo -n" и ничего не выведет.


-

предыдущий рабочий каталог. [дефис] Команда cd - выполнит переход в предыдущий рабочий каталог, путь к которому хранится в переменной окружения $OLDPWD .

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

-

Минус. Знак минус в арифметических операциях.

=

Символ "равно". Оператор присваивания

a=28

echo $a # 28


В зависимости от контекста применения, символ "=" может выступать в качестве оператора сравнения.

+

Плюс. Оператор сложения в арифметических операциях.

В зависимости от контекста применения, символ + может выступать как оператор регулярного выражения.

+

Ключ (опция). Дополнительный флаг для ключей (опций) команд.

Отдельные внешние и встроенные команды используют символ "+" для разрешения некоторой опции, а символ "-" -- для запрещения.

%

модуль. Модуль (остаток от деления) -- арифметическая операция.

В зависимости от контекста применения, символ % может выступать в качестве шаблона.

~

домашний каталог. [тильда] Соответствует содержимому внутренней переменной $HOME. ~bozo -- домашний каталог пользователя bozo, а команда ls ~bozo выведет содержимое его домашнего каталога. ~/ -- это домашний каталог текущего пользователя, а команда ls ~/ выведет содержимое домашнего каталога текущего пользователя.