KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Мендель Купер - Искусство программирования на языке сценариев командной оболочки

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Мендель Купер, "Искусство программирования на языке сценариев командной оболочки" бесплатно, без регистрации.
Перейти на страницу:

#+ в именах которых содержатся пробелы, заменяя пробелы символом подчеркивания.

Пример A-4. blank-rename: переименование файлов, чьи имена содержат пробелы

Это даже более простая версия предыдущего примера.

#! /bin/bash

# blank-rename.sh

#

# Заменяет пробелы символом подчеркивания в именах файлов в текущем каталоге.


ONE=1 # единственное или множественное число (см. ниже).

number=0 # Количество переименованных файлов.

FOUND=0 # Код завершения в случае успеха.


for filename in * # Перебор всех файлов в текущем каталоге.

do

echo "$filename" | grep -q " " # Проверить -- содержит ли имя файла

if [ $? -eq $FOUND ] #+ пробелы.

then

fname=$filename # Удалить путь из имени файла.

n=`echo $fname | sed -e "s/ /_/g"` # Заменить пробелы символом подчеркивания.

mv "$fname" "$n" # Переименование.

let "number += 1"

fi

done


if [ "$number" -eq "$ONE" ]

then

echo "$number файл переименован."

else

echo "Переименовано файлов: $number"

fi


exit 0

Пример A-5. encryptedpw: Передача файла на ftp-сервер, с использованием пароля

#!/bin/bash


# Модификация примера "ex72.sh", добавлено шифрование пароля.


# Обратите внимание: этот вариант все еще нельзя считать безопасным,

#+ поскольку в сеть пароль уходит в незашифрованном виде.

# Используйте "ssh", если вас это беспокоит.


E_BADARGS=65


if [ -z "$1" ]

then

echo "Порядок использования: `basename $0` имя_файла"

exit $E_BADARGS

fi


Username=bozo # Измените на свой.

pword=/home/bozo/secret/password_encrypted.file

# Файл, содержащий пароль в зашифрованном виде.


Filename=`basename $1` # Удалить путь из имени файла


Server="XXX"

Directory="YYY" # Подставьте фактические имя сервера и каталога.


Password=`cruft <$pword` # Расшифровка.

# Используется авторская программа "cruft",

#+ основанная на алгоритме "onetime pad",

#+ ее можно скачать с :

#+ Primary-site: ftp://ibiblio.org/pub/Linux/utils/file

#+ cruft-0.2.tar.gz [16k]


ftp -n $Server <<End-Of-Session

user $Username $Password

binary

bell

cd $Directory

put $Filename

bye

End-Of-Session

# ключ -n, команды "ftp", запрещает автоматический вход.

# "bell" -- звонок (звуковой сигнал) после передачи каждого файла.


exit 0

Пример A-6. copy-cd: Копирование компакт-дисков с данными

#!/bin/bash

# copy-cd.sh: copying a data CD


CDROM=/dev/cdrom # устройство CD ROM

OF=/home/bozo/projects/cdimage.iso # промежуточный файл

# /xxxx/xxxxxxx/ измените для своей системы.

BLOCKSIZE=2048

SPEED=2 # Можно задать более высокую скорость, если поддерживается.


echo; echo "Вставьте исходный CD, но *НЕ* монтируйте его."

echo "Нажмите ENTER, когда будете готовы. "

read ready # Ожидание.


echo; echo "Создается промежуточный файл $OF."

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


dd if=$CDROM of=$OF bs=$BLOCKSIZE # Копирование.


echo; echo "Выньте исходный CD."

echo "Вставьте чистую болванку CDR."

echo "Нажмите ENTER, когда будете готовы. "

read ready # Ожидание.


echo "Копируется файл $OF на болванку."


cdrecord -v -isosize speed=$SPEED dev=0,0 $OF

# Используется пакет Joerg Schilling -- "cdrecord" .

# http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html


echo; echo "Копирование завершено."


echo "Желаете удалить промежуточный файл (y/n)? " # Наверняка большой файл получился.

read answer


case "$answer" in

[yY]) rm -f $OF

echo "Файл $OF удален."

;;

*) echo "Файл $OF не был удален.";;

esac


echo


# Упражнение:

# Добавьте в оператор "case" возможность обработки, введенных пользователем, "yes" и "Yes".


exit 0

Пример A-7. Последовательности Коллаца (Collatz)

#!/bin/bash

# collatz.sh


# Широко известная последовательность Коллаца (Collatz) (гипотеза Коллаца).

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

# 1) Принимает из командной строки "начальное" целое число.

# 2) ЧИСЛО <--- НАЧАЛЬНОЕ ЗНАЧЕНИЕ

# 3) Вывести ЧИСЛО.

# 4) Если ЧИСЛО четное, разделить на 2,

# 5)+ Если не четное -- умножить на 3 и прибавить 1.

# 6) ЧИСЛО <--- РЕЗУЛЬТАТ

# 7) Повторить, начиная с п. 3, заданное число раз.

#

# Теоретически, такая последовательность должна сходиться,

#+ не зависимо от величины начального значения,

#+ к повторению циклов "4,2,1...",

#+ даже после значительных флуктуаций в самом начале.


MAX_ITERATIONS=200

# Для больших начальных значений (>32000), это значение придется увеличить.


h=${1:-$$} # Начальное значение

# если из командной строки ничего не задано, то берется $PID,


echo

echo "C($h) --- $MAX_ITERATIONS итераций"

echo


for ((i=1; i<=MAX_ITERATIONS; i++))

do


echo -n "$h "

# ^^^^^

# табуляция


let "remainder = h % 2"

if [ "$remainder" -eq 0 ] # Четное?

then

let "h /= 2" # Разделить на 2.

else

let "h = h*3 + 1" # Умножить на 3 и прибавить 1.

fi


COLUMNS=10 # Выводить по 10 значений в строке.

let "line_break = i % $COLUMNS"

if [ "$line_break" -eq 0 ]

then

echo

fi


done


echo


exit 0

Пример A-8. days-between: Подсчет числа дней между двумя датами

#!/bin/bash

# days-between.sh: Подсчет числа дней между двумя датами.

# Порядок использования: ./days-between.sh [M]M/[D]D/YYYY [M]M/[D]D/YYYY


ARGS=2 # Ожидается два аргумента из командной строки.

E_PARAM_ERR=65 # Ошибка в числе ожидаемых аргументов.


REFYR=1600 # Начальный год.

CENTURY=100

DIY=365

ADJ_DIY=367 # Корректировка на високосный год + 1.

MIY=12

DIM=31

LEAPCYCLE=4


MAXRETVAL=255 # Максимально возможное возвращаемое значение

# для положительных чисел.


diff= # Количество дней между датами.

value= # Абсолютное значение.

day= # день, месяц, год.

month=

year=


Param_Error () # Ошибка в пвраметрах командной строки.

{

echo "Порядок использования: `basename $0` [M]M/[D]D/YYYY [M]M/[D]D/YYYY"

echo " (даты должны быть после 1/3/1600)"

exit $E_PARAM_ERR

}


Parse_Date () # Разбор даты.

{

month=${1%%/**}

dm=${1%/**} # День и месяц.

day=${dm#*/}

let "year = `basename $1`" # Хотя это и не имя файла, но результат тот же.

}


check_date () # Проверка даты.

{

[ "$day" -gt "$DIM" ] || [ "$month" -gt "$MIY" ] || [ "$year" -lt "$REFYR" ] && Param_Error

# Выход из сценария при обнаружении ошибки.

# Используется комбинация "ИЛИ-списка / И-списка".

#

# Упражнение: Реализуйте более строгую проверку даты.

}


strip_leading_zero () # Удалить ведущий ноль

{

val=${1#0} # иначе Bash будет считать числа

return $val # восьмеричными (POSIX.2, sect 2.9.2.1).

}


day_index () # Формула Гаусса:

{ # Количество дней от 3 Янв. 1600 до заданной даты.


day=$1

month=$2

year=$3


let "month = $month - 2"

if [ "$month" -le 0 ]

then

let "month += 12"

let "year -= 1"

fi


let "year -= $REFYR"

let "indexyr = $year / $CENTURY"


let "Days = $DIY*$year + $year/$LEAPCYCLE - $indexyr + $indexyr/$LEAPCYCLE + $ADJ_DIY*$month/$MIY + $day - $DIM"

# Более подробное объяснение алгоритма вы найдете в

# http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm


if [ "$Days" -gt "$MAXRETVAL" ] # Если больше 255,

then # то поменять знак

let "dindex = 0 - $Days" # чтобы функция смогла вернуть полное значение.

else let "dindex = $Days"

fi


return $dindex


}


calculate_difference () # Разница между двумя датами.

{

let "diff = $1 - $2" # Глобальная переменная.

}


abs () # Абсолютное значение

{ # Используется глобальная переменная "value".

if [ "$1" -lt 0 ] # Если число отрицательное

then # то

let "value = 0 - $1" # изменить знак,

else # иначе

let "value = $1" # оставить как есть.

fi

}


if [ $# -ne "$ARGS" ] # Требуется два аргумента командной строки.

then

Param_Error

fi


Parse_Date $1

check_date $day $month $year # Проверка даты.


strip_leading_zero $day # Удалить ведущие нули

day=$? # в номере дня и/или месяца.

strip_leading_zero $month

month=$?


day_index $day $month $year

date1=$?


abs $date1 # Абсолютное значение

date1=$value


Parse_Date $2

check_date $day $month $year


strip_leading_zero $day

day=$?

strip_leading_zero $month

month=$?


day_index $day $month $year

date2=$?


abs $date2 # Абсолютное значение

date2=$value


calculate_difference $date1 $date2


abs $diff # Абсолютное значение

diff=$value


echo $diff


exit 0

# Сравните этот сценарий с реализацией формулы Гаусса на C

# http://buschencrew.hypermart.net/software/datedif

Пример A-9. Создание "словаря"

#!/bin/bash

# makedict.sh [создание словаря]


# Модификация сценария /usr/sbin/mkdict.

# Авторские права на оригинальный сценарий принадлежат Alec Muffett.

#

# Этот модифицированный вариант включен в документ на основе

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*