LXF135:Bash

Материал из Linuxformat.

(Различия между версиями)
Перейти к: навигация, поиск
(викификация, оформление, иллюстрация)
(''Bash'': Про­стые и бы­ст­рые скрип­ты)
Строка 43: Строка 43:
Ко­ман­да ста­ла не на­мно­го ко­ро­че, но не­мно­го изящ­нее, и ес­ли спи­сок воз­мож­ных рас­ши­ре­ний фай­лов бу­дет рас­ти, вы сэ­ко­но­ми­те вре­мя и си­лы. Применяйте этот при­ем в бу­ду­щих скрип­тах. Те­перь, убе­див­шись, что изу­че­ние скрип­тов ''Bash'' мо­жет весь­ма при­го­дить­ся, при­ос­та­но­вим­ся и рас­смот­рим, чтоже та­кое ''Bash''.
Ко­ман­да ста­ла не на­мно­го ко­ро­че, но не­мно­го изящ­нее, и ес­ли спи­сок воз­мож­ных рас­ши­ре­ний фай­лов бу­дет рас­ти, вы сэ­ко­но­ми­те вре­мя и си­лы. Применяйте этот при­ем в бу­ду­щих скрип­тах. Те­перь, убе­див­шись, что изу­че­ние скрип­тов ''Bash'' мо­жет весь­ма при­го­дить­ся, при­ос­та­но­вим­ся и рас­смот­рим, чтоже та­кое ''Bash''.
-
{{Врезка|Содержание[[Изображение:=LXF135_81_1.jpg|300px]] Ваш ком­пь­ю­тер с Linux на­фар­ши­ро­ван скрип­та­ми. В '''/etc/init.d''' вы най­де­те при­ме­ры скрип­тов, управ­ляю­щих сис­тем­ны­ми сер­ви­са­ми.|Ширина=300px}}
+
{{Врезка|Содержание=[[Изображение:=LXF135_81_1.jpg|300px]] Ваш ком­пь­ю­тер с Linux на­фар­ши­ро­ван скрип­та­ми. В '''/etc/init.d''' вы най­де­те при­ме­ры скрип­тов, управ­ляю­щих сис­тем­ны­ми сер­ви­са­ми.|Ширина=300px}}
Ес­ли вы бе­ре­тесь за де­ло все­рь­ез, най­ди­те се­бе удоб­ный тек­сто­вый ре­дак­тор. В ''Emacs, Vi, Gedit'' и ''Kate'' есть под­свет­ка син­так­си­са для ''Bash'', и это плюс. Сре­да обо­лоч­ки – про­сто сре­да: сце­на или ок­ру­же­ние, в ко­то­ром обыч­ные ко­ман­ды мо­гут вы­пол­нять свои обя­зан­но­сти. Поч­ти ка­ж­дая ко­ман­да, ко­то­рую вы ко­гда-ли­бо вы­пол­ня­ли и ко­то­рая что-то де­ла­ет, не за­ви­сит от обо­лоч­ки, но без обо­лоч­ки у этих ко­манд не бу­дет ра­бо­че­го кон­тек­ста. Скры­тая за внеш­ним лос­ком ши­кар­но­го Gnome/KDE/дру­го­го гра­фи­че­ско­го ин­тер­фей­са обо­лоч­ка жиз­нен­но не­об­хо­ди­ма для ра­бо­ты ком­пь­ю­те­ра – он и за­пус­тить­ся не смог бы без сре­ды, где вы­пол­ня­ют­ся ко­ман­ды. Стро­ка за стро­кой, скром­ные скрип­ты Bash при за­груз­ке сис­те­мы на­страи­ва­ют сеть, мон­ти­ру­ют уст­рой­ст­ва, за­пус­ка­ют сер­ви­сы, от­кры­ва­ют окон­ный ме­нед­жер; и множество скрип­тов ра­бо­та­ет в фо­но­вом ре­жи­ме, вы­пол­няя скры­тые за­да­чи под­держ­ки ОС в ра­бо­чем со­стоя­нии.
Ес­ли вы бе­ре­тесь за де­ло все­рь­ез, най­ди­те се­бе удоб­ный тек­сто­вый ре­дак­тор. В ''Emacs, Vi, Gedit'' и ''Kate'' есть под­свет­ка син­так­си­са для ''Bash'', и это плюс. Сре­да обо­лоч­ки – про­сто сре­да: сце­на или ок­ру­же­ние, в ко­то­ром обыч­ные ко­ман­ды мо­гут вы­пол­нять свои обя­зан­но­сти. Поч­ти ка­ж­дая ко­ман­да, ко­то­рую вы ко­гда-ли­бо вы­пол­ня­ли и ко­то­рая что-то де­ла­ет, не за­ви­сит от обо­лоч­ки, но без обо­лоч­ки у этих ко­манд не бу­дет ра­бо­че­го кон­тек­ста. Скры­тая за внеш­ним лос­ком ши­кар­но­го Gnome/KDE/дру­го­го гра­фи­че­ско­го ин­тер­фей­са обо­лоч­ка жиз­нен­но не­об­хо­ди­ма для ра­бо­ты ком­пь­ю­те­ра – он и за­пус­тить­ся не смог бы без сре­ды, где вы­пол­ня­ют­ся ко­ман­ды. Стро­ка за стро­кой, скром­ные скрип­ты Bash при за­груз­ке сис­те­мы на­страи­ва­ют сеть, мон­ти­ру­ют уст­рой­ст­ва, за­пус­ка­ют сер­ви­сы, от­кры­ва­ют окон­ный ме­нед­жер; и множество скрип­тов ра­бо­та­ет в фо­но­вом ре­жи­ме, вы­пол­няя скры­тые за­да­чи под­держ­ки ОС в ра­бо­чем со­стоя­нии.

Версия 11:56, 8 октября 2011

Учебник Bash Bash Из­вер­ни­тесь в Linux, сэ­ко­но­мив вре­мя и уп­ро­стив се­бе жизнь

Содержание

Bash: Про­стые и бы­ст­рые скрип­ты

На­пи­сать по­лез­ный скрипт про­сто. В пер­вой час­ти на­шей но­вой се­рии о про­грам­ми­ро­ва­нии Ник Вейч при­гла­ша­ет вас по­рез­вить­ся с Bash.

А ведь вы уже мо­же­те пи­сать скрип­ты (сце­на­рии) Bash – раз­ве что они не очень слож­ны. Ри­ск­ну пред­по­ло­жить, что ча­ще все­го в ко­манд­ной стро­ке вы при­ме­няе­те та­кой скрипт:

> ls
a.png a.txt bash1.sh b.png b.txt c.txt x.jpg y.jpg z.gif

Да, это скрипт Bash. Нет, прав­да – но толь­ко в нем все­го од­на стро­ка. В нем не ис­поль­зу­ют­ся спе­ци­аль­ные воз­мож­но­сти Bash, про­сто вы­пол­ня­ет­ся про­стая ко­ман­да для вы­во­да со­дер­жи­мо­го те­ку­ще­го ка­та­ло­га. Все еще не ве­ри­те? Сде­ла­ем кое-что еще. Ска­жем, вы ри­ск­ну­ли вы­вес­ти со­дер­жи­мое ка­та­ло­га в под­роб­ном ви­де:

> ls -l
total 4
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 a.png
-rw-rw-r--. 1 evilnick evilnick 2868 Jun 29 12:55 a.txt
-rw-rw-r--. 1evilnick evilnick 151 Jun 29 12:49 bash1.sh
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 b.png
-rw-rw-r--. 1evilnick evilnick 223 Jun 29 12:55 b.txt
-rw-rw-r--. 1 evilnick evilnick 120 Jun 29 12:56 c.txt
-rw-rw-r--. 1 evilnick evilnick 3486 Jun 29 12:56 x.jpg
-rw-rw-r--. 1 evilnick evilnick 3486 Jun 29 12:56 y.jpg
-rw-rw-r--. 1 evilnick evilnick 19273 Jun 29 12:56 z.gif

Ну не кру­то? Мы вос­поль­зо­ва­лись «клю­чом», оп­ци­ей ко­ман­ды ls, ко­то­рый вы­во­дит бо­лее под­роб­ную ин­фор­ма­цию. Те­перь, до­пус­тим, нуж­но вы­вес­ти спи­сок всех фай­лов изо­бра­же­ний. Как это сде­лать? По­про­бу­ем:

> ls -l *.png
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 a.png
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 b.png

Ага! Спец­сим­вол * – не часть ко­ман­ды ls, а часть обо­лоч­ки Bash. Bash ин­тер­пре­ти­ру­ет ко­ман­ду, встре­ча­ет спец­сим­вол и за­ме­ня­ет его со­от­вет­ст­вую­щи­ми зна­че­ния­ми. Итак, мы пи­шем скрипт Bash! Од­на из вы­год до­ба­воч­ных зна­ний о Bash и о ра­бо­те обо­лоч­ки в том, что вы мо­же­те взгля­нуть на про­бле­му ши­ре и сде­лать что-то чуть бо­лее ум­ное и по­лез­ное:

>ls -l *.{gif,png,jpg}
-rw-rw-r--. 1evilnick evilnick 2450 Jun 29 12:55 a.png
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 b.png
-rw-rw-r--. 1 evilnick evilnick 3486 Jun 29 12:56 x.jpg
-rw-rw-r--. 1 evilnick evilnick 3486 Jun 29 12:56 y.jpg
-rw-rw-r--. 1 evilnick evilnick 19273 Jun 29 12:56 z.gif

Что же тут про­изош­ло? Это од­на из са­мых про­стых уло­вок, ко­то­рые мож­но най­ти в скрип­тах Bash – рас­кры­тие ско­бок. В об­щем слу­чае, Bash рас­кры­ва­ет со­дер­жи­мое ско­бок как все, что идет пе­ред скоб­ка­ми (или по­сле) плюс ка­ж­дый от­дель­ный эле­мент внут­ри ско­бок. В дан­ном слу­чае, по­сле рас­кры­тия ско­бок мы по­лу­чим ко­ман­ду ls -l *.gif *.jpg *.png.

Ко­ман­да ста­ла не на­мно­го ко­ро­че, но не­мно­го изящ­нее, и ес­ли спи­сок воз­мож­ных рас­ши­ре­ний фай­лов бу­дет рас­ти, вы сэ­ко­но­ми­те вре­мя и си­лы. Применяйте этот при­ем в бу­ду­щих скрип­тах. Те­перь, убе­див­шись, что изу­че­ние скрип­тов Bash мо­жет весь­ма при­го­дить­ся, при­ос­та­но­вим­ся и рас­смот­рим, чтоже та­кое Bash.

Изображение:=LXF135 81 1.jpg Ваш ком­пь­ю­тер с Linux на­фар­ши­ро­ван скрип­та­ми. В /etc/init.d вы най­де­те при­ме­ры скрип­тов, управ­ляю­щих сис­тем­ны­ми сер­ви­са­ми.

Ес­ли вы бе­ре­тесь за де­ло все­рь­ез, най­ди­те се­бе удоб­ный тек­сто­вый ре­дак­тор. В Emacs, Vi, Gedit и Kate есть под­свет­ка син­так­си­са для Bash, и это плюс. Сре­да обо­лоч­ки – про­сто сре­да: сце­на или ок­ру­же­ние, в ко­то­ром обыч­ные ко­ман­ды мо­гут вы­пол­нять свои обя­зан­но­сти. Поч­ти ка­ж­дая ко­ман­да, ко­то­рую вы ко­гда-ли­бо вы­пол­ня­ли и ко­то­рая что-то де­ла­ет, не за­ви­сит от обо­лоч­ки, но без обо­лоч­ки у этих ко­манд не бу­дет ра­бо­че­го кон­тек­ста. Скры­тая за внеш­ним лос­ком ши­кар­но­го Gnome/KDE/дру­го­го гра­фи­че­ско­го ин­тер­фей­са обо­лоч­ка жиз­нен­но не­об­хо­ди­ма для ра­бо­ты ком­пь­ю­те­ра – он и за­пус­тить­ся не смог бы без сре­ды, где вы­пол­ня­ют­ся ко­ман­ды. Стро­ка за стро­кой, скром­ные скрип­ты Bash при за­груз­ке сис­те­мы на­страи­ва­ют сеть, мон­ти­ру­ют уст­рой­ст­ва, за­пус­ка­ют сер­ви­сы, от­кры­ва­ют окон­ный ме­нед­жер; и множество скрип­тов ра­бо­та­ет в фо­но­вом ре­жи­ме, вы­пол­няя скры­тые за­да­чи под­держ­ки ОС в ра­бо­чем со­стоя­нии.

Сде­ла­ем боль­ше

Мно­гие ска­жут, что Bash хо­рош для про­стых за­дач, но не го­дит­ся, ко­гда де­ло до­хо­дит до серь­ез­ных ве­щей, вро­де взаи­мо­дей­ст­вия по се­ти. Хо­тя в та­ких слу­ча­ях под­ход Bash и в са­мом де­ле не­мно­го труд­нее и нуд­нее (а так­же и ме­нее по­зна­ва­ем), это от­нюдь не зна­чит, что поль­зо­вать­ся им нель­зя, и мы рас­смот­рим не­сколь­ко по­доб­ных при­ме­ров в бу­ду­щем. А что ка­са­ет­ся при­чи­ны поль­зо­вать­ся Bash, ко­гда то же са­мое лег­ко сде­лать на Python или PHP... ну, ино­гда Bash – это все, что у вас есть. Мы уже от­ме­ти­ли, что прак­ти­че­ски во всех вер­си­ях Linux, встраи­вае­мых и про­чих, есть Bash или Bash-по­доб­ная сре­да; по­это­му не ху­до и знать, на что спо­соб­ны да­же про­стей­шие ути­ли­ты.

Пер­вое, что сле­ду­ет рас­смот­реть – как мы по­сту­пи­ли бы в слу­чае язы­ка про­грам­ми­ро­ва­ния – это ис­поль­зо­ва­ние пе­ре­мен­ных. О раз­ных ти­пах дан­ных забудьте, по­сколь­ку тип в ос­нов­ном один: стро­ки. Но стро­ки очень гиб­кие. Взгля­ни­те на ко­рот­кий при­мер:

> foo=”ploppy”
> echo $foo
ploppy
> echo $foo+1
ploppy+1
> foo=”ls”
> echo $foo
ls
> foo=”$foo -al”
> echo $foo
ls -al
> echo ‘$foo’
$foo
> echo “$foo”
ls -al
> $foo *.png
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 a.png
-rw-rw-r--. 1 evilnick evilnick 2450 Jun 29 12:55 b.png

Пре­ж­де все­го от­ме­тим, что пе­ре­мен­ная оп­ре­де­ля­ет­ся пу­тем вво­да ее име­ни, зна­ка ра­вен­ст­ва и зна­че­ния. Не ок­ру­жай­те знак ра­вен­ст­ва про­бе­ла­ми, ина­че Bash вы­даст ошиб­ку. Име­на пе­ре­мен­ных долж­ны на­чи­нать­ся с бу­к­вы или сим­во­ла под­чер­ки­ва­ния и мо­гут со­дер­жать циф­ры, бу­к­вы и сим­во­лы под­чер­ки­ва­ния.

Есть со­гла­ше­ние за­да­вать все име­на пе­ре­мен­ных в верх­нем ре­ги­ст­ре. Од­на­ко при­сут­ст­ву­ет мно­же­ст­во встро­ен­ных пе­ре­мен­ных и пе­ре­мен­ных ок­ру­же­ния, и за­да­вая име­на соб­ст­вен­ных пе­ре­мен­ных в ниж­нем ре­ги­ст­ре, час­то мож­но из­бе­жать кон­флик­та имен.

Так как пе­ре­мен­ная яв­ля­ет­ся стро­кой, ус­та­нов­ка зна­че­ния «не­что+1» про­сто до­пи­шет к стро­ке ‘+1’. Об ариф­ме­ти­че­ских опе­ра­ци­ях мы вкрат­це по­го­во­рим по­том.

Знак $ пе­ред име­нем пе­ре­мен­ной внут­ри двой­ных ка­вы­чек при­ве­дет к то­му, что ее зна­че­ние бу­дет рас­кры­то. А внут­ри оди­ноч­ных ка­вы­чек Bash не де­ла­ет ни­ка­ких под­ста­но­вок, и вы по­лу­чи­те про­сто ли­те­рал.

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

Не­что по­лез­ное

Пре­ж­де чем по­гря­зать в де­та­лях, рас­смот­рим од­ну шту­ку, спо­соб­ную при­го­дить­ся при на­пи­са­нии скрип­та. Вот пол­ный скрипт, ко­то­рый мож­но за­пус­тить на до­маш­нем ком­пь­ю­те­ре. Вся­кие там пе­ре­мен­ные де­ла­ют в нем свои де­лиш­ки. На­бе­ри­те этот код в тек­сто­вом ре­дак­то­ре, со­хра­ни­те под име­нем example1.sh и за­пус­ти­те из обо­лоч­ки ко­ман­дой bash example1.sh:

#!/bin/bash
 ROOT_UID=0
 ERROR_PERMISSION=77
 if [$UID” != “$ROOT_UID]
 then
   echo “You must run this script as root”
   exit $ERROR_PERMISSION
 fi
 exit 0

Пер­вая стро­ка на­чи­на­ет­ся с ком­би­на­ции сим­во­лов, час­то на­зы­вае­мой «ша­лаш» [shebang] – #!. Это осо­бый вид стро­ки ком­мен­та­рия, ко­то­рая со­об­ща­ет вы­звав­шей ее обо­лоч­ке, что ес­ли стро­ку вы­пол­нять как ко­ман­ду, ее нуж­но пе­ре­дать ис­пол­няе­мо­му фай­лу, путь к ко­то­ро­му ука­зан да­лее. Ко­ро­че го­во­ря, это про­сто спо­соб вы­пол­нить скрипт. Пе­рей­дем к бо­лее ин­те­рес­но­му…

Пом­ни­те, мы го­во­ри­ли, что из Bash мож­но об­ра­щать­ся к пе­ре­мен­ным ок­ру­же­ния? UID – од­на из этих пе­ре­мен­ных; она со­дер­жит иден­ти­фи­ка­тор поль­зо­ва­те­ля (в ви­де чис­ла), за­пус­тив­ше­го обо­лоч­ку Bash. Это чис­ло рав­но 0 для су­пер­поль­зо­ва­те­ля-root, а для обык­но­вен­ных поль­зо­ва­те­лей за­ви­сит от ис­поль­зуе­мо­го ди­ст­ри­бу­ти­ва; обыч­но для пер-во­го поль­зо­ва­те­ля бе­рет­ся 501.

Скорая помощь

Сто­ит вве­сти в при­выч­ку за­кан­чи­вать скрипт ко­ман­дой exit 0, ес­ли все дей­ст­вия за­вер­ши­лись ус­пеш­но. При связ­ке скрип­тов друг с дру­гом ус­ло­вия вы­хо­да важ­ны.

Вы­ра­же­ние if – стан­дарт­ный опе­ра­тор ус­ло­вия. Ана­ли­зи­руе­мое ус­ло­вие помещает­ся в  квад­рат­ных скоб­ках. Здесь мы ис­поль­зу­ем опе­ра­тор срав­не­ния !=, ко­то­рый оз­на­ча­ет «не рав­но» (и его так­же мож­но запи­сать как “ -ne “). От­сю­да яс­но, что ес­ли иден­ти­фи­ка­тор поль­зо­ва­те­ля ра­вен зна­че­нию пе­ре­мен­ной для root, ус­ло­вие внут­ри квад­рат­ных ско­бок лож­но и скрипт пе­ре­хо­дит к вы­ра­же­нию fi, по­сле срав­не­ния. Ес­ли зна­че­ния не рав­ны, вы­пол­не­ние пе­ре­хо­дит к ко­ман­дам по­сле then, мы по­лу­ча­ем со­об­ще­ние и скрипт за­вер­ша­ет­ся.

Не счи­тая ря­да за­ре­зер­ви­ро­ван­ных зна­че­ний (0–2, 126–165 и 255), же­ст­ких пра­вил на­счет ко­дов вы­хо­да нет. По со­гла­ше­нию, для оши­бок, свя­зан­ных с от­ка­зом в дос­ту­пе, час­то ис­поль­зу­ет­ся 77, но мож­но упот­реб­лять и свои ко­ды вы­хо­да; глав­ное – пом­нить, что они оз­на­ча­ют.

Итак, наш скрипт ни­че­го не де­ла­ет, но мо­жет стать на­ча­лом дру­го­го, бо­лее плодотвор­но­го. Он дос­та­точ­но безо­па­сен – обыч­но из Bash нель­зя из­ме­нить зна­че­ние UID, но бо­лее по­ле­зен как про­вер­ка пе­ред вы­пол­не­ни­ем не­ких дей­ст­вий, тре­бую­щих прав дос­ту­па root. Bash под­дер­жи­ва­ет кон­ст­рук­ции else и elif; так­же су­ще­ст­ву­ют осо­бые опе­ра­то­ры срав­не­ния. Сле­дую­щий ма­лень­кий скрипт про­ве­ря­ет, су­ще­ст­ву­ет ли за­дан­ный ка­та­лог, и вы­во­дит со­от­вет­ст­вую­щее со­об­ще­ние:

#!/bin/bash
 CHECKDIR=”examples”
 if [ -d $CHECKDIR ]
 then
   echo “examples directory exists”
 else
   echo “examples directory does not exist!”
 fi
 exit 0

Па­ра­метр -d внут­ри квад­рат­ных ско­бок – спе­ци­аль­ный опе­ра­тор, про­ве­ряю­щий, су­ще­ст­ву­ет ли ка­та­лог в фай­ло­вой сис­те­ме. Сле­дую­щий ар­гу­мент – имя ка­та­ло­га; в дан­ном слу­чае мы пе­ре­да­ли его че­рез пе­ре­мен­ную. Дру­гие опе­ра­то­ры срав­не­ния см. во врез­ке спра­ва ввер­ху на со­сед­ней стра­ни­це.

За­цик­ли­ва­ем­ся

Мы уже по­зна­ко­ми­лись со стан­дарт­ным опе­ра­то­ром срав­не­ния. Дру­гая кон­ст­рук­ция, час­то при­ме­няе­мая в про­грам­ми­ро­ва­нии – цикл. В Bash су­ще­ст­ву­ют раз­лич­ные ти­пы цик­лов, но ча­ще все­го ис­поль­зу­ет­ся for... do... done. В Bash его мож­но сде­лать очень по­хо­жим на цикл в C или в дру­гих язы­ках, ко­то­ры­ми вы, воз­мож­но, поль­зо­ва­лись:

for (( i = 0 ; i < 10 ; i++ ))
 do
   echo $i
 done

Впро­чем, как и в Python, ите­ра­ция в Bash обыч­но осу­ще­ст­в­ля­ет­ся по спи­ску зна­че­ний – в на­шем при­ме­ре его ге­не­ри­ру­ют внут­рен­ние скоб­ки. Ча­ще все­го вы уви­ди­те цик­лы с ите­ра­ция­ми по мас­си­ву или по спи­ску, сге­не­ри­ро­ван­но­му из дру­гих зна­че­ний. На­при­мер:

for i in $(ls)
 do
  echo $i
 done

Bash, как все­гда, вы­чис­ля­ет со­дер­жи­мое ско­бок. В дан­ном слу­чае это ко­ман­да, и Bash ее вы­пол­ня­ет и соз­да­ет спи­сок ре­зуль­та­тов, по ко­то­ро­му за­тем бу­дет про­из­во­дить­ся ите­ра­ция. Поз­же мы под­роб­нее по­го­во­рим о мас­си­вах (ко­то­рые в Bash по су­ти од­но­мер­ные и боль­ше по­хо­жи на объ­ект спи­ска в Python), но ча­ще все­го они ис­поль­зу­ют­ся та­ким об­ра­зом:

> array=(becky tabitha sue)
 > echo $array
 becky
 > echo $array[1]
 becky[1]
 > echo ${array[1]}
 tabitha
 > echo ${array[@]}
 becky tabitha sue
 > for i in ${array[@]}
 > do
 > echo $i
 > done
 becky
 tabitha
 sue

Про­сек­ли фишку? По­смот­ри­те сно­ва: квад­рат­ные скоб­ки ис­поль­зу­ют­ся для ссыл­ки на мас­сив по ин­дек­сам, но Bash не обя­зан знать, что при­став­лен­ное в кон­це че­го-то [1] оз­на­ча­ет ин­декс. В по­ряд­ке об­хо­да, нуж­но по­сле $ ок­ру­жить все, что от­но­сит­ся к пе­ре­мен­ной, в фи­гур­ные скоб­ки, га­ран­ти­руя об­ра­бот­ку это­го как еди­ной сущ­но­сти. Ес­ли по­про­бо­вать по­лу­чить дос­туп к мас­ си­ву без ин­дек­са, вы про­сто по­лу­чи­те пер­вый эле­мент (а ин­дек­сы на­чи­на­ют­ся с 0). Ин­декс [@] — осо­бое зна­че­ние, ко­то­рое рас­ши­ря­ет­ся до всех зна­че­ний, хра­ни­мых в мас­си­ве, и мы ис­поль­зу­ем его в по­след­нем цик­ле for для ге­не­ра­ции спи­ска.

И в ито­ге

Для соз­да­ния скрип­тов Bash не тре­бу­ет­ся ни­че­го, кро­ме тер­ми­на­ла. На­строй­те его по­на­гляд­нее и соз­дай­те ка­та­лог для экс­пе­ри­мен­тов.

Воо­ру­жив­шись изу­чен­ны­ми прие­ма­ми, на­пи­шем не­что по­лез­ное: ко­рот­кий скрипт. Бу­ду­чи за­пу­щен в ка­та­ло­ге, он най­дет все фай­лы изо­бра­же­ний оп­ре­де­лен­но­го ти­па и пе­ре­мес­тит их в соб­ст­вен­ный под­ка­та­лог images:

#!/bin/bash
 filetypes=( jpg png gif )
 IMGDIR=”images”
 if [ -d $IMGDIR ]
 then
   echo “directory already exists, continuing...”
 else
   mkdir $IMGDIR
 fi
 for type in ${filetypes[@]}
 do
   for i in $( ls *.$type )
   do
     echo “this file $i is being moved”
     mv $i $IMGDIR
   done
 done
 exit 0

Это мож­но сде­лать и ком­пакт­нее, но по ко­ду, струк­ту­ри­ро­ван­но­му та­ким об­ра­зом, про­ще по­нять, что про­ис­хо­дит. Мы соз­да­ли мас­сив для хра­не­ния ти­пов фай­лов, ко­то­рые нуж­но ото­брать; за­тем вос­поль­зо­ва­лись опе­ра­то­ром if…, что­бы по­нять, су­ще­ст­ву­ет ли ка­та­лог на­зна­че­ния, или соз­дать его в про­тив­ном слу­чае.

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

Со­хра­нив файл, вы­пол­ни­те ко­ман­ду

chmod ugo+x sortimage.sh

Она ус­та­но­вит бит ис­пол­не­ния для скрип­та, и его мож­но бу­дет за­пус­кать на­пря­мую, без ко­ман­ды bash.

В те­ку­щей вер­сии скрип­та эта ко­ман­да бу­дет по­лу­чать ра­бо­чий ка­та­лог из лю­бо­го мес­та в фай­ло­вой сис­те­ме, от­ку­да вы ее за­пус­кае­те. Файл мож­но бы­ло бы со­хра­нить в /usr/sbin или где угодно еще в пу­ти ко­ман­ды и вы­зы­вать ее от­ку­да вам заблагорассудится.

Итак, мы об­на­ру­жи­ли, что вы знае­те о Bash го­раз­до боль­ше, чем вам ка­за­лось, уз­на­ли, как поль­зо­вать­ся пе­ре­мен­ны­ми, и по­зна­ко­ми­лись с ос­нов­ны­ми кон­ст­рук­ция­ми скрип­та. На сле­дую­щем уроке мы по­го­во­рим о вклю­че­нии в скрипт внеш­них ко­манд и их за­пус­ке че­рез Bash, и до­ба­вим ин­те­рак­тив­но­сти ва­шим про­грам­мам, на­пи­сав соб­ст­вен­ный скрипт ре­зерв­но­го ко­пи­ро­ва­ния. До встре­чи!


Дру­гие по­лез­ные срав­не­ния

Для дру­гих ва­ри­ан­тов ус­ло­вий по­ме­щай­те в скоб­ки опе­ра­то­ра срав­не­ния та­кие кон­ст­рук­ции:

[ -a $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет.
[ -d $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и это ка­та­лог.
[ -f $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и это обык­но­вен­ный файл.
[ -h $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и это сим­во­ли­че­ская ссыл­ка.
[ -r $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и его мож­но про­чи­тать.
[ -s $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и его раз­мер боль­ше ну­ля.
[ -w $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и в не­го мож­но пи­сать.
[ -x $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и он ис­пол­няе­мый.
[ -O $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и его вла­дель­цем яв­ля­ет­ся поль­зо­ва­тель с дей­ст­вую­щим иден­ти­фи­ка­то­ром поль­зо­ва­те­ля.
[ -N $FIlE ] Ис­тин­но, ес­ли $FILE су­ще­ст­ву­ет и из­ме­нил­ся с мо­мен­та по­след­не­го чте­ния.
[ $FIlE1 -nt $FIlE2 ] Ис­тин­но, ес­ли $FILE1 из­ме­нил­ся поз­же $FILE2 или ес­ли $FILE1 су­ще­ст­ву­ет, а $FILE2 нет.
[ $FIlE1 -ot $FIlE2 ] Ис­тин­но, ес­ли $FILE1 стар­ше, чем $FILE2, или ес­ли $FILE2 су­ще­ст­ву­ет, а $FILE1 – нет.
[ $FIlE1 -ef $FIlE2 ] Ис­тин­но, ес­ли $FILE1 и $FILE2 ссы­ла­ют­ся на один и тот же файл.

Хит­ро­сти с кла­ви­ша­ми

В Bash пре­ду­смот­ре­но мно­же­ст­во ком­би­на­ций кла­виш, и они бо­лее или ме­нее со­от­вет­ст­ву­ют ком­би­на­ци­ям кла­виш Emacs, так что ес­ли вы с ни­ми зна­ко­мы, это пре­иму­ще­ст­во. Вот не­сколь­ко са­мых цен­ных – по край­ней ме­ре, по­про­буй­те за­пом­нить те, что пока­жут­ся вам по­лез­ны­ми:

HOME Пе­ре­ме­ща­ет кур­сор в на­ча­ло стро­ки.
END Пе­ре­ме­ща­ет кур­сор в ко­нец стро­ки.
Стрел­ка вверх Вос­ста­нав­ли­ва­ет пре­ды­ду­щую ко­ман­ду.
Стрел­ка вниз Вос­ста­нав­ли­ва­ет сле­дую­щую ко­ман­ду.
Ctrl+R Ищет по­след­нюю ко­ман­ду в ис­то­рии, со­дер­жа­щую ука­зан­ные сим­во­лы.
Ctrl+O Вы­пол­ня­ет ко­ман­ду, най­ден­ную с по­мо­щью Ctrl+R.
Ctrl+L Очи­ща­ет эк­ран.
Ctrl+U Очи­ща­ет со­дер­жи­мое стро­ки пе­ред кур­со­ром.
Ctrl+K Очи­ща­ет со­дер­жи­мое стро­ки по­сле кур­со­ра.
Ctrl+C От­прав­ля­ет те­ку­щей за­да­че сиг­нал SIGINT, ко­то­рый обыч­но за­вер­ша­ет ее.
Ctrl+Z От­прав­ля­ет те­ку­щей за­да­че сиг­нал SIGTSTP, ко­то­рый при­ос­та­но­вит ее. (За­тем ее мож­но во­зоб­но­вить ко­ман­дой fg). Что­бы вер­нуть­ся к ней поз­же, мож­но на­брать fg [‘имя про­цес­са или иден­ти­фи­ка­тор за­да­ния’].
Alt+F Пе­ре­ме­ща­ет кур­сор на од­но сло­во впе­ред в стро­ке.
Alt+B Пе­ре­ме­ща­ет кур­сор на од­но сло­во на­зад в стро­ке.
Alt+Del Уда­ля­ет сло­во пе­ред кур­со­ром.
Alt+D Уда­ля­ет сло­во по­сле кур­со­ра.
Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию