BASH Programming - Introduction HOW-TO, 27 июля 2000 г.

Данная статья предназначена для того, чтобы помочь Вам начать программировать shell-скрипты начального и среднего уровня. Она не претендует на то, чтобы быть продвинутым руководством (см. заглавие). Автор НЕ ЯВЛЯЕТСЯ ни экспертом, ни гуру в shell-программировании. Автор решил написать это, потому что многое изучает, и это может быть полезно для других людей. Любые обратные связи приветствуются, особенно в patch-форме :-)

[Mike G mikkey, перевод: Дмитрий А. Смирнов]

1. Введение

1.1 Получение последних версий

http://www.linuxdoc.org/HOWTO/Bash-Prog-Intro-HOWTO.html

1.2 Что необходимо

Знакомство с командной строкой, также полезно знакомство с основными концепциями программирования. Хотя это не учебник по программированию, здесь объясняются (или, по крайней мере, делается попытка объяснить) многие основные концепции.

1.3 Использование данного документа

Данный документ пытается быть полезным в следующих ситуациях:

  • У вас есть идея, связанная с программированием и Вы хотите начать кодировать какие-нибудь shell-скрипты.
  • У вас расплывчатая идея, связанная с программированием и Вам нужны какие-нибудь указания.
  • Вы хотите посмотреть на какие-нибудь shell-скрипты и комментарии, чтобы начать писать свои собственные.
  • Вы мигрируете из DOS/Windows (или уже сделали это) и хотите создавать файлы пакетной обработки ("batch").
  • Вы - полный нерд и читаете любой доступный how-to.

2. Простейшие скрипты

В данном HOW-TO делается попытка дать Вам некоторые советы по shell-программированию, основанные строго на примерах.

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

2.1 Традиционный скрипт "hello world"

          #!/bin/bash          
          echo Hello World    
        

В данном скрипте всего две строки. Первая сообщает системе, какая программа используется для запуска файла.

Вторая строка - это единственное действие, выполняемое данным скриптом, печатающее 'Hello world' на терминале.

Если Вы получите что-то типа ./hello.sh: Command not found. то, возможно, первая строка '#!/bin/bash' неправильная; запустите whereis bash или посмотрите finding bash, чтобы выяснить, какой должна быть эта строка.

2.2 Очень простой скрипт резервного копирования

        #!/bin/bash          
        tar -cZf /var/my-backup.tgz /home/me/
        

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

3. Всё о перенаправлении

3.1 Теория и беглый взгляд

Есть 3 файловых дескриптора: stdin - cтандартный ввод, stdout - стандартный вывод и stderr - стандартный поток ошибок.

Ваши основные возможности:

  1. перенаправлять stdout в файл
  2. перенаправлять stderr в файл
  3. перенаправлять stdout в stderr
  4. перенаправлять stderr в stdout
  5. перенаправлять stderr и stdout в файл
  6. перенаправлять stderr и stdout в stdout
  7. перенаправлять stderr и stdout в stderr
1 означает stdout, а 2 - stderr.

Небольшое примечание для понимания: с помощью команды less Вы можете смотреть как stdout, который остаётся в буфере, так и stderr, который печатается на экране, но стирается, когда Вы пытаетесь "просмотреть" буфер.

3.2 Пример: stdout в файл

Это действие записывает стандартный вывод программы в файл.

        ls -l > ls-l.txt
        
Здесь создаётся файл, названный 'ls-l.txt', и в нём будет содержаться то, что бы Вы увидели, если бы ввели команду 'ls -l' и выполнили её.

3.3 Пример: stderr в файл

Это действие записывает стандартный поток ошибок программы в файл.

        grep da * 2> grep-errors.txt
        
Здесь создаётся файл, названный 'grep-errors.txt', и в нём будет содержаться часть вывода команды 'grep da *', относящаяся к стандартному потоку ошибок.

3.4 Пример: stdout в stderr

Это действие записывает стандартный вывод программы туда же, куда и стандартный поток ошибок.

        grep da * 1>&2 
        
Здесь стандартный вывод команды посылается в стандартный поток ошибок, Вы можете увидеть это разными путями.

3.5 Sample: stderr 2 stdout

Это действие записывает стандартный поток ошибок программы туда же, куда и стандартный вывод.

        grep * 2>&1
        
Здесь стандартный поток ошибок команды посылается на стандартный вывод; если Вы перешлёте результат через конвейер (|) в less, то увидите, что строки, которые обычно пропадают (как записанные в стандартный поток ошибок) в этом случае сохраняются (потому что они на стандартном выводе).

3.6 Пример: stderr и stdout в файл

Это действие помещает весь вывод программы в файл. Это иногда подходит для cron'овских заданий, если Вы хотите, чтобы команда выполнялась абсолютно незаметно.

        rm -f $(find / -name core) &> /dev/null 
        
Это (предположим, на cron'овском задании) удаляет любой файл с названием 'core' в любом каталоге. Помните, что Вы должны быть полностью уверены в том, что делает команда, если хотите затереть её вывод.

4. Конвейеры

Данный раздел объясняет очень простым и практичным способом, как использовать конвейеры и почему Вам это может понадобиться.

4.1 Что это такое и зачем Вам это использовать

Конвейеры позволяют Вам использовать (я убеждён, что очень просто) вывод одной программы как вход другой.

4.2 Пример: простой конвейер с sed

Это очень простой способ использовать конвейеры.

        ls -l | sed -e "s/[aeio]/u/g"
        
Здесь происходит следующее: сначала выполняется команда ls -l, её вывод, вместо того чтобы отображаться на экране, посылается в программу sed, которая, в свою очередь, выводит на экран то, что должна.

4.3 Пример: альтернатива для ls -l *.txt

Возможно, это намного более сложный способ, чем ls -l *.txt, но он здесь только для иллюстрации работы с конвейерами, а не для решения вопроса выбора из этих двух способов листинга.

        ls -l | grep "\.txt$"
        
Здесь вывод программы ls -l посылается в программу grep, которая, в свою очередь, выводит на экран строки, соответствующие регулярному выражению "\.txt$".

5. Переменные

Вы можете использовать переменные так же, как в любом языке программирования. Типов данных нет. Переменная в bash может представлять собой число, символ, строку символов.

Вам не нужно объявлять переменную, присвоение значения на её указатель как раз и создаёт её.

5.1 Пример: "Hello World!", использующий переменные

            #!/bin/bash          
            STR="Hello World!"
            echo $STR    
            

Вторая строка создаёт переменную, которая называется STR, и присваивает ей строчное значение "Hello World!". Затем ЗНАЧЕНИЕ этой переменной извлекается при добавлении знака '$' в начале. Пожалуйста, запомните (постарайтесь) что если Вы не используете знак '$', вывод программы может быть другим, и вероятно, не таким, как Вы хотите.

5.2 Пример: очень простой скрипт резервного копирования (немного получше)

#!/bin/bash
OF=/var/my-backup-$(date +%Y%m%d).tgz  #OF - Output File - выходной файл
tar -cZf $OF /home/me/
           

Данный скрипт вводит ещё одно понятие. Прежде всего Вам следует разобраться со второй строкой. Обратите внимание на выражение '$(date +%Y%m%d)'. Если Вы запустите этот скрипт, то заметите, что он выполняет команду внутри скобок, перехватывая её вывод.

Заметьте, что в этом скрипте имя выходного файла будет меняться каждый день, исходя из формата ключа к команде date (+%Y%m%d). Вы можете это поменять заданием другого формата.

Другие примеры:

echo ls

echo $(ls)

5.3 Локальные переменные

Локальные переменные могут быть созданы при использовании ключевого слова local.

                #!/bin/bash
                HELLO=Hello 
                function hello {
                        local HELLO=World
                        echo $HELLO
                }
                echo $HELLO
                hello
                echo $HELLO
        

Данного примера должно быть достаточно, чтобы показать, как использовать локальные переменные.

6. Условные операторы

Условные операторы позволяют Вам решать, выполнять ли действие или нет, решение принимается при вычислении значения выражения.

6.1 Сухая теория

Существует много форм условных операторов. Элементарная форма - это if выражение then оператор где 'оператор' выполняется только тогда, когда 'выражение' имеет значение "истина". '2<1' - это выражение, имеющее значение "ложь", в то время как '2>1' - "истина".

Существуют другие формы условных операторов, такие как: if выражение then оператор1 else оператор2. Здесь 'оператор1' выполняется, если 'выражение' истина , иначе выполняется 'оператор2'.

Ещё одна форма условных операторов - это: if выражение1 then оператор1 else if выражение2 then оператор2 else оператор3. В этой форме добавляется только последовательность "ELSE IF 'выражение2' THEN 'оператор2'", заставляющая 'оператор2' выполняться, если 'выражение2' имеет значение "истина". Всё остальное так, как Вы себе представляете (см. предыдущие формы).

Немного о синтаксисе:

Элементарная конструкция оператора 'if' в bash выглядет так:

if [выражение];

then

code if 'выражение' is true.

fi

6.2 Пример: элементарный пример условного оператора if .. then

            #!/bin/bash
            if [ "foo" = "foo" ]; then
               echo выражение вычислилось как истина
            fi
            

Код, выполняемый, если выражение внутри квадратных скобок - истина, находится после слова 'then' и перед словом 'fi', которое обозначает конец исполняемого при выполнении условия кода.

6.3 Пример: элементарный пример условного оператора if .. then ... else

            #!/bin/bash
            if [ "foo" = "foo" ]; then
               echo выражение вычислилось как истина
            else
               echo выражение вычислилось как ложь
            fi
            

6.4 Пример: условные операторы с переменными

            #!/bin/bash
            T1="foo"
            T2="bar"
            if [ "$T1" = "$T2" ]; then
                echo выражение вычислилось как истина
            else
                echo выражение вычислилось как ложь
            fi
            

7. Циклы for, while и until

В этом разделе Вы познакомитесь с циклами for, while и until.

Цикл for немного отличается от аналогов в других языках программирования. Прежде всего, он позволяет Вам проводить последовательные действия над "словами" в строке.

Цикл while выполняет кусок кода, когда проверяемое выражение - истина и останавливается только тогда, когда оно - ложь (или внутри исполняемого кода встречается явно заданное прерывание цикла).

Цикл until почти равносилен циклу while, только код выполняется, когда проверяемое выражение - ложь.

Если Вы считаете, что while и until очень похожи, Вы правы.

7.1 Пример цикла for

        #!/bin/bash
        for i in $( ls ); do
            echo item: $i
        done
        

Во второй строке мы объявляем i как переменную, которая получает различные значения, содержащиеся в $( ls ).

Третья строка при необходимости могла бы быть длиннее или там могло бы быть несколько строк перед done (4-я строка).

'done' (4-я строка) показывает, что код, в котором используется значение $i, заканчивается и $i получает новое значение.

Данный скрипт имеет совсем не большой смысл, более полезным применением цикла for было бы использование его для отбора только каких-то определённых файлов в предыдущем примере.

7.2 C-подобный for

fiesh предложил добавить эту форму цикла. Это цикл for, более похожий на for в языках C, Perl и т.п.

        #!/bin/bash
        for i in `seq 1 10`;
        do
                echo $i
        done
        

7.3 Пример цикла while

         #!/bin/bash
         COUNTER=0
         while [  $COUNTER -lt 10 ]; do
             echo The counter is $COUNTER
             let COUNTER=COUNTER+1
         done
         

Данный скрипт "эмулирует" хорошо известную (в языках C, Pascal, perl и т.д.) структуру 'for'.

7.4 Пример цикла until

         #!/bin/bash
         COUNTER=20
         until [  $COUNTER -lt 10 ]; do
             echo COUNTER $COUNTER
             let COUNTER-=1
         done
         

8. Функции

Как почти в любом языке программирования, Вы можете использовать функции для группировки кусков кода более логичным способом или для практического применения волшебного искусства рекурсии.

Объявление функции - это всего лишь запись function my_func { my_code }.

Вызов функции осуществляется точно так же, как и вызов других программ, Вы просто пишете её имя.

8.1 Пример функций

           #!/bin/bash
           function quit {
               exit
           }
           function hello {
               echo Hello!
           }
           hello
           quit
           echo foo
           

В строках 2-4 содержится функция 'quit'. В строках 5-7 - функция 'hello'. Если Вам не совсем ясно, что делает данный скрипт, испытайте его!

Заметьте, что что функции не обязательно объявлять в каком-то определённом порядке.

Если Вы запустите скрипт, то заметите, что сначала вызывается функция 'hello', затем функция 'quit', и программа никогда не достигает 10-й строки.

8.2 Пример функций с параметрами

                #!/bin/bash
                function quit {
                   exit
                }
                function e {
                    echo $1
                }
                e Hello
                e World
                quit
                echo foo

           

Данный скрипт почти идентичен предыдущему. Главное отличие - это функция 'e'. Эта функция выводит первый аргумент, который получает. Аргументы в функциях обрабатываются так же, как и аргументы переданные скрипту.

9. Интерфейсы пользователя

9.1 Использование select для создания простых меню

           #!/bin/bash
           OPTIONS="Hello Quit"
           select opt in $OPTIONS; do
               if [ "$opt" = "Quit" ]; then
                echo done
                exit
               elif [ "$opt" = "Hello" ]; then
                echo Hello World
               else
                clear
                echo bad option
               fi
           done
          

Если Вы запустите этот скрипт, то увидите, что это - мечта программиста о меню на текстовой основе. Вы, вероятно, заметите, что это очень похоже на конструкцию 'for', только вместо циклической обработки каждого "слова" в $OPTIONS программа спрашивает пользователя.

9.2 Использование командной строки

#!/bin/bash
if [ -z "$1" ]; then
    echo используйте: $0 каталог
    exit
fi
SRCD=$1                      #SRCD - SouRCe Directory - исходный каталог
TGTD="/var/backups/"         #TGTD - TarGeT Directory - конечный каталог
OF=home-$(date +%Y%m%d).tgz  #OF - Output File - выходной файл
tar -cZf $TGTD$OF $SRCD
         

Что делает этот скрипт, Вам должно быть понятно. Выражение в первом условном операторе проверяет, получила ли программа аргумент ($1) и, если нет, завершает работу программы, показывая пользователю небольшое сообщение об ошибке. Оставшаяся часть скрипта на данный момент, очевидно, понятна.

10. Разное

10.1 Чтение пользовательского ввода с помощью read

В некоторых случаях вы, возможно, захотите попросить пользователя что-нибудь ввести. Есть разные способы сделать это. Вот один из способов:

                #!/bin/bash
                echo Введите, пожалуйста, Ваше имя
                read NAME
                echo "Привет, $NAME!"
        

Как вариант, Вы можете получать сразу несколько значений с помощью read, данный пример объясняет это:

          #!/bin/bash
          echo "Введите, пожалуйста, Ваши имя и фамилию"
          read FN LN   #FN - First Name - имя; LN - Last Name - фамилия
          echo "Hi! $LN, $FN !"
        

10.2 Арифметические вычисления

В командной строке (или оболочке) попробуйте ввести следующее:

echo 1 + 1

Если Вы рассчитываете увидеть '2', то будете разочарованы. Что делать, если Вы хотите, чтобы BASH произвёл вычисления над Вашими числами? Вот решение:

echo $((1+1))

В результате этого будет более "логичный" вывод. Такая запись используется для вычисления арифметических выражений. Вы также можете сделать это следующим образом:

echo $[1+1]

Если Вам нужно использовать дроби или более сложную математику, или Вы просто это хотите, можете использовать bc для вычисления арифметических выражений.

Когда автор запустил "echo $[3/4]" в командной оболочке, она вернула значение 0, т.к. bash, когда отвечает, использует только целые значения. Если Вы запустите "echo 3/4|bc -l", оболочка вернёт правильное значение 0.75.

10.3 Ищем bash

Из сообщения от mike (см. Благодарности):

Вы всегда используете #!/bin/bash .. Вы могли бы привести пример, как найти, где расположен bash.

Предпочтительно использовать 'locate bash', но не на всех машинах есть locate.

'find ./ -name bash' из корневого каталога обычно срабатывает.

Можно проверить следующие расположения:

ls -l /bin/bash

ls -l /sbin/bash

ls -l /usr/local/bin/bash

ls -l /usr/bin/bash

ls -l /usr/sbin/bash

ls -l /usr/local/sbin/bash

(сходу не могу придумать никакой другой каталог... Я находил bash в большинстве этих мест на различных системах).

Вы также можете попробовать 'which bash'.

10.4 Получение возвратного значения программы

В bash возвратное значение программы сохраняется в специальной переменной $?.

Данный пример иллюстрирует, как перехватить возвратное значение программы; я предположил, что каталога dada не существует (это также предложил mike).

        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?
        

10.5 Перехват вывода команды

Этот маленький скрипт показывает все таблицы из всех баз данных (предполагается, что у вас установлен MySQL). Также, подумайте о том, как поправить команду 'mysql' для использования подходящего имени пользователя и пароля.

        #!/bin/bash
        DBS=`mysql -uroot  -e"show databases"`
        for b in $DBS ;
        do
                mysql -uroot -e"show tables from $b"
        done
        

10.6 Несколько исходных файлов

Вы можете запускать несколько файлов файлы с помощью команды source.

__TO-DO__

11. Таблицы

11.1 Операторы сравнения строк

(1) s1 = s2

(2) s1 != s2

(3) s1 < s2

(4) s1 > s2

(5) -n s1

(6) -z s1

(1) s1 совпадает с s2

(2) s1 не совпадает с s2

(3) s1 в алфавитном порядке предшествует s2 (в соответствие с текущей локалью)

(4) s1 в алфавитном порядке следует после s2 (в соответствие с текущей локалью)

(5) s1 имеет ненулевое значение (содержит один символ или более)

(6) s1 имеет нулевое значение

11.2 Примеры сравнения строк

Сравнение двух строк.

        #!/bin/bash
        S1='string'
        S2='String'
        if [ $S1=$S2 ];
        then
                echo "S1('$S1') не равна to S2('$S2')"
        fi
        if [ $S1=$S1 ];
        then
                echo "S1('$S1') равна to S1('$S1')"
        fi
        

Тут автор процитирует замечание из письма, которое прислал Андреас Бек, связанное с использованием if [ $1 = $2 ].

Это не совсем хорошая идея, т.к. если либо $S1, либо $S2 - пустая строка, Вы получите синтаксическую ошибку. Лучше использовать x$1 = x$2 или "$1" = "$2" .

11.3 Arithmetic operators

+

-

*

/

% (remainder)

11.4 Арифметические операторы сравнения

-lt (<)

-gt (>)

-le (<=)

-ge (>=)

-eq (==)

-ne (!=)

Программистам на C следует просто выбрать оператор, соответствующий выбранному оператору в скобках.

11.5 Полезные команды

Этот раздел переписал Kees (см. Благодарности).

Некоторые из этих команд практически содержат полноценные командные языки. Здесь объясняются только основы таких команд. Для более подробной информации внимательно просмотрите man-страницы каждой команды.

sed (потоковый редактор)

Sed - это неинтерактивный редактор. Вместо того, чтобы изменять файл движением курсора на экране, Вы используете сценарий инструкций по редактированию для sed плюс имя редактируемого файла. Вы также можете рассматривать sed как фильтр. Посмотрите на некоторые примеры:

        $sed 's/to_be_replaced/replaced/g' /tmp/dummy
        

Sed заменяет строку 'to_be_replaced' строкой 'replaced', читая файл /tmp/dummy . Результат посылается на стандартный вывод (обычно на консоль), но Вы также можете добавить '> capture' в вышеприведённую строку, чтобы sed посылал вывод в файл 'capture'.

        $sed 12, 18d /tmp/dummy
        

Sed показывает все строки, за исключением строк с 12 по 18. Исходный файл этой командой не изменяется.

awk (манипулирование файлами данных, выборка и обработка текста)

Существует много реализаций языка программирования AWK (наиболее известные интерпретаторы - это gawk из проекта GNU и "новый awk" mawk.) Принцип простой: AWK ищет шаблон и для каждого подходящего шаблона выполняется какое-нибудь действие.

Автор снова создал файл dummy, содержащий следующие строки:

"test123

test

tteesstt"

        $awk '/test/ {print}' /tmp/dummy
        

test123

test

Шаблон, который ищет AWK - это 'test', а действие, которое AWK выполняет, когда найдёт строку в /tmp/dummy с подстрокой 'test' - это 'print'.

        $awk '/test/ {i=i+1} END {print i}' /tmp/dummy
        

3

Если Вы ищете несколько шаблонов, замените текст между кавычками на '-f file.awk', в этом случае Вы можете записать все шаблоны и действия в файле 'file.awk'.

grep (выводит строки, соответствующие искомому шаблону)

Мы уже рассматривали несколько команд grep в предыдущих главах, которые отображали строки, соответствующие шаблону. Но grep может делать большее.

        $grep "look for this" /var/log/messages -c
        

12

Строка "look for this" была найдена 12 раз в файле /var/log/messages.

[ok, данный пример был фикцией, /var/log/messages был переделан :-)]

wc (считает строки, слова и байты)

В следующем примере мы видим, что выводится не то, что мы ожидаем. Файл dummy в этом случае содержит следующий текст:

"bash introduction

howto test file"

        $wc --words --lines --bytes /tmp/dummy
        

2 5 34 /tmp/dummy

wc не заботится о порядке параметров. wc всегда выводит их в стандартном порядке, в таком, как Вы видите: <число строк><число слов><число байт><имя файла>.

sort (сортирует строки текстового файла)

На этот раз файл dummy содержит следующий текст:

"b

c

a"

        $sort /tmp/dummy
        

Вот как выглядит вывод:

a

b

c

Команды не должны быть такими простыми :-)

bc (вычислительный язык программирования)

bc производит вычисления с командной строки (ввод из файла, но не через перенаправление или конвейер), а также из пользовательского интерфейса. Следующий пример показывает некоторые команды. Заметьте, что автор использовал bc с параметром -q, чтобы отказаться от вывода сообщения с приглашением.

   $bc -q
        

1 == 5

0

0.05 == 0.05

1

5 != 5

0

2 ^ 8

256

sqrt(9)

3

while (i != 9) {

i = i + 1;

print i

}

123456789

quit

tput (инициализирует терминал или запрашивает базу данных terminfo)

Небольшая демонстрация возможностей tput:

        $tput cup 10 4
        

Приглашение командной строки появится в координатах (y10,x4).

        $tput reset
        

Очищается экран, и приглашение появляется в (y1,x1). Заметьте, что (y0,x0) - это левый верхний угол.

        $tput cols
        
80

Показывает возможное число символов в направлении по оси x.

Очень рекомендуется быть на ты с этими программами (как минимум). Существуют тонны маленьких программ, которые позволят Вам заняться настоящей магией в командной строке.

[Некоторые примеры были взяты из man-страниц или FAQ'ов.]

12. Ещё скрипты

12.1 Применение команды ко всем файлам в каталоге.

12.2 Пример: очень простой скрипт резервного копирования (немного получше)

#!/bin/bash
SRCD="/home/"                #SRCD - SouRCe Directory - исходный каталог
TGTD="/var/backups/"         #TGTD - TarGeT Directory - конечный каталог
OF=home-$(date +%Y%m%d).tgz  #OF - Output File - выходной файл
tar -cZf $TGTD$OF $SRCD
           

12.3 Программа, переименовывающая файлы

          
#!/bin/sh
# renna: переименование нескольких файлов по специальным правилам
# Автор - felix hudson Jan - 2000

#Прежде всего, посмотрите на различные "режимы", которые есть у этой программы.
#Если первый аргумент ($1) подходит, то мы выполняем эту часть
#программы и затем выходим.

# Проверка на условие добавления префикса.
if [ $1 = p ]; then

#Теперь сдвигаемся от переменной режима ($1) и префикса ($2)
prefix=$2 ; shift ; shift

# Быстренько проверим, задан ли хотя бы один файл.
# Если нет, то лучше ничего не делать, чем переименовывать несуществующие
# файлы!!

  if [$1 = ]; then
     echo "не задано ни одного файла"
     exit 0
  fi

# Этот цикл for проделывает итерации над всеми файлами, которые мы задали
# программе.
# Он делает одно переименование на файл.
  for file in $*
    do
    mv ${file} $prefix$file
  done

#Теперь выходим из программы.
  exit 0
fi

# Проверка на условие добавления суффикса.
# В остальном эта часть фактически идентична предыдущему разделу;
# смотрите, пожалуйста, комментарии оттуда.
if [ $1 = s ]; then
  suffix=$2 ; shift ; shift
  if [$1 = ]; then
   echo "не задано ни одного файла"
   exit 0
  fi

 for file in $*
  do
   mv ${file} $file$suffix
 done

 exit 0
fi

# Проверка на условие переименования с заменой.
if [ $1 = r ]; then

  shift

# Я включил этот кусок, чтобы не повредить ни один файл, если пользователь
# не определил, что сделать -
# простая мера безопасности:

  if [ $# -lt 3 ] ; then
    echo "Ошибка; правильный ввод: renna r [выражение] [замена] файлы... "
    exit 0
  fi

# Сдвигаемся к другой информации
  OLD=$1 ; NEW=$2 ; shift ; shift

# Данный цикл for последовательно проходит через все файлы, которые мы 
# задали программе.
# Он совершает одно переименование на файл, используя программу 'sed'.
# Это простая программа с командной строки, которая анализирует стандартный 
# ввод и заменяет регулярное выражение на заданную строку.
# Здесь мы задаём для sed имя файла (как стандартный ввод) и заменяем
# нужный текст.

  for file in $*
  do
    new=`echo ${file} | sed s/${OLD}/${NEW}/g`
    mv ${file} $new
  done
exit 0
fi

# Если мы дошли до этой строки, это значит, что программе были заданы
# неправильные параметры. Поэтому мы расскажем пользователю, как её
# использовать
echo "используйте:"
echo " renna p [префикс] файлы.."
echo " renna s [суффикс] файлы.."
echo " renna r [выражение] [замена] файлы.."
exit 0

# done!
             
          

12.4 Программа, переименовывающая файлы (простая)

     #!/bin/bash
     # renames.sh
     # простая переименовывающая программа

     criteria=$1
     re_match=$2
     replace=$3
     
     for i in $( ls *$criteria* ); 
     do
         src=$i
         tgt=$(echo $i | sed -e "s/$re_match/$replace/")
         mv $src $tgt
     done
     

13. Если что-то не так (отладка)

13.1 Как вызвать BASH

Хорошо было бы добавить в первую строку

          #!/bin/bash -x
          

В результате этого будет выводится некоторая интересная выходная информация.

14. О документе

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

14.1 Гарантии (никаких)

Данный документ поставляется без каких-либо гарантий и т.д.

14.2 Переводы

Итальянский: Вильям Гельфи (William Ghelfi, wizzy at tiscalinet.it) здесь - http://web.tiscalinet.it/penguin_rules

Французский: Лорент Мартелли (Laurent Martelli) is missed

Корейский: Минсок Парк (Minseok Park) http://kldp.org/

Корейский: Чхун Хе Чин (Chun Hye Jin) unknown

Испанский: Габриэль Родригес Альберич (Gabriel Rodri'guez Alberich) http://www.insflug.org/

Нидерландский: Эллен Бокхорст (Ellen Bokhorst) http://nl.linux.org/

Словенский: Андрей Лайовиц (Andrej Lajovic) http://www.lugos.si/

По мнению автора, есть ещё переводы, но у него нет никакой информации о них, если у Вас она есть, пришлите её автору и он обновит этот раздел.

14.3 Благодарности

  • Людям, переводившим этот документ на другие языки (предыдущий раздел).
  • Нэйтану Херсту (Nathan Hurst) за то, что прислал много исправлений.
  • Джону Абботту (Jon Abbott) за то, что прислал комментарии по поводу вычислений арифметических выражений.
  • Феликсу Хадсону (Felix Hudson) за написание скрипта renna
  • Кесу ван ден Бруку (Kees van den Broek) (за то, что прислал много исправлений и переписал полезный раздел по командам)
  • Mike (pink) дал ряд советов по поводу местоположения bash и тестирования файлов
  • Fiesh дал хороший совет для раздела по циклам.
  • Lion предложил упомянуть о распространённой ошибке (./hello.sh: Command not found.)
  • Андреас Бек (Andreas Beck) сделал несколько исправлений и комментариев.

14.4 История

Добавлены информация о новых переводах и немного исправлений.

Добавлен переписанный Kess'ом раздел по полезным командам.

Сделан ряд исправлений и дополнений.

Добавлены примеры по сравнению строк.

v0.8 Отказ от нумерации версий, я думаю, что даты достаточно.

v0.7 Ещё исправления и написаны некоторые старые разделы TO-DO.

v0.6 Небольшие исправления.

v0.5 Добавлен раздел по перенаправлению.

v0.4 Документ исчез там, где располагался, из-за экс-босса автора и нашёл себе место на предназначенном для него сайте: www.linuxdoc.org.

Предыдущее: автор не помнит, он не использовал ни rcs, ни cvs :(

14.5 Другие источники

Введение в bash (под BE) - http://org.laol.net/lamug/beforever/bashtut.htm

Программирование на Bourne Shell - http://207.213.123.70/book/

14.6 Примечание переводчика

Перевод распространяется на условиях лицензии GPL2.

Текущая версия перевода находится на Линукс-странице переводчика:

http://daslinux.da.ru/.

Высказывайте свои комментарии, замечания и предложения в гостевой книге на странице или по адресу: das@cabel.net.

[ опубликовано 26/01/2003 ]

Mike G mikkey, перевод: Дмитрий А. Смирнов - BASH Programming - Introduction HOW-TO, 27 июля 2000 г.   Версия для печати