Юникс Кунг-Фу

За что мы любим Юник­со­по­доб­ные ОС? Ну, за вся­кое, но не в послед­нюю оче­редь за их отлич­ные команд­ные стро­ки. Конеч­но, мож­но писать скрип­ты или даже неболь­шие про­грам­ки на Пер­ле али Питоне, но если надо быст­ро что-то авто­ма­ти­зи­ро­вать, то луч­ше все­го писать какой-нибудь one-liner типа:

cat file | grep something | sed ‘s/thing/otherthing/’ | awk ‑F «|» ‘{print $1}’ | sort | uniq | wc ‑l

И всё тут пре­крас­но, но здесь совер­шен­но отсут­ству­ет услов­ное ветв­ле­ние — а это ино­гда полез­но.

Напри­мер, мож­но ска­зать вот так:

cd directory; rm ‑rf *

Что будет, если cd directory обло­мит­ся, пото­му что этой дирек­то­рии нет? Нач­нёт выпол­нять­ся rm ‑rf в ТЕКУЩЕЙ дирек­то­рии — что может иметь ката­стро­фи­че­ские послед­ствия.

Как это­го избе­жать? Очень про­сто. Надо ска­зать вот так:

cd directory && rm ‑rf *

В дан­ном слу­чае rm ‑rf выпол­нит­ся ТОЛЬКО если cd directory будет успеш­но выпол­нен.

Рабо­та­ет это очень про­сто — если понять, что дан­ное выра­же­ние пред­став­ля­ет собой не боль­ше, чем усло­вие с Сиш­ным син­так­си­сом. && — это опе­ра­тор AND. Любая коман­да при завер­ше­нии рабо­ты выда­ёт код воз­вра­та (exit status). Если коман­да завер­ши­лась успеш­но, воз­вра­ща­ет­ся код 0, он же явля­ет­ся TRUE. Опе­ра­тор && под­ра­зу­ме­ва­ет что ОБЕ части усло­вия долж­ны воз­вра­щать TRUE, поэто­му если пер­вое усло­вие вер­ну­ло TRUE, надо про­ве­рять вто­рое. Если же пер­вое вер­ну­ло FALSE, то нет смыс­ла про­ве­рять вто­рое (прин­цип мини­ма­ли­за­ции про­вер­ки усло­вий https://en.wikipedia.org/wiki/Short-circuit_evaluation).

Соот­вет­ствен­но, мож­но вывер­нуть это наизнан­ку, если исполь­зо­вать опе­ра­тор || (сиречь OR) меж­ду коман­да­ми. В таком слу­чае вто­рая часть выра­же­ния будет выпол­не­на толь­ко в том слу­чае, если пер­вая вер­нёт FALSE — ибо в соот­вет­ствии с прин­ци­пом мини­ма­ли­за­ции нет смыс­ла про­ве­рять вто­рую часть усло­вия, где усло­вия объ­еде­ни­ны через OR — ибо пер­вая уже вер­ну­ла TRUE.

Напри­мер, вот так:

cd test|| mkdir test

Дирек­то­рия test будет созда­на толь­ко в том слу­чае, если её нет (cd вер­нёт ошиб­ку).

Так­же мож­но объ­еди­нять усло­вия, исполь­зуя тот же Сиш­ный син­так­сис.

(cd directory && rm ‑rf *) || echo «Cannot delete files»

Если мож­но зай­ти в дирек­то­рию и уда­лить там фай­лы, то ниче­го не высве­тит­ся. Но если нель­зя, будет ска­за­но, что нель­зя.

Дан­ные коман­ды рабо­та­ют в bash и C‑shell. BSD-шный sh не про­ве­рял, но думаю, что там тоже будет рабо­тать.