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.

#

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

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