вторник, 1 сентября 2009 г.

Что означают фигурные скобки в командной строке?

Авторы: Алексей Дмитриев, Даник Лейбович, июль-август 2009

Фигурные скобки {по-английски - brace} это один из условных знаков, помогающих сократить количество писанины в командной строке.

Формально они входят в число семи expansions (расширение, раскрытие), применяемых в командной строке шелла bash.

Что это за расширения такие? По-русски их лучше всего назвать сокращениями, как это ни странно. Смотрите сами: всем известная тильда (~), будучи напечатана в командной строке, раскроется в путь к нашему домашнему каталогу:

$ ls ~

bookmarks1.html dos Pictures
cv.avi Gnome-ppp RPM
Desktop hasher Tanya
Documents tmp

Вот и выходит, что тильда является сокращением адреса /home/имя_пользователя.

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

Раскрытие фигурных скобок

Допустим, что нам нужно создать для фотоальбома двенадцать каталогов (по числу месяцев) 2009 года. Мы можем поступить так:
$ mkdir фото_01_2009 фото_02_2009 ... фото_12_2009

(вместо троеточия впишем имена всех промежуточных каталогов).

А можем привлечь на помощь сокращение - фигурные скобки:

$ mkdir фото_{01,02,03,04,05,06,07,08,09,10,11,12}_2009

Проделайте этот опыт и сами убедитесь, что в рабочей директории появилось 12 новых каталогов. Чтобы они нам в дальнейшем не мешали, удалим их:

$ rm -R фото_{01,02,03,04,05,06,07,08,09,10,11,12}_2009

Проверьте - их больше нет.

Однако интуиция подсказывает, что должен существовать и более короткий путь, и этот путь, конечно, есть:

$ mkdir фото_{01..12}_2009

А для более сложных сочетаний даже:

$ mkdir фото_{{01..05},07,{09..12}}_2009

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

Чтобы закончить с этим примером, отметим, что в выражении фото_{01,02,03,04,05,06,07,08,09,10,11,12}_2009, часть выражения фото_ будет называться префиксом (а по-нашему - приставкой), а _2009 называется суффиксом (или окончанием).

Вот еще пример применения фигурных скобок:

Нужно изменить права доступа к нескольким файлам: old, current и new, находящимся в одной директории:

$ chmod u+x /путь_к_директории/{old,current,new}

Мы применили фигурные скобки, чтобы не писать имена и пути (path) всех трех файлов полностью.

Осторожно, скобки раскрываются

Существует несколько правил, которые соблюдаются при раскрывании фигурных скобок:

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

Например, мы можем создать файлы пес.txt и кот.txt командой:

$ touch {пес.txt,кот.txt}

И они будут благополучно созданы.

$ ls

кот.txt
пес.txt

Но, стоит внутрь фигурных скобок проникнуть пробелу, как начнется нечто несуразное:

$ touch {пес.txt ,кот.txt}

Проверим, что вышло:

$ ls

{пес.txt
,кот.txt}

Мы получили два файла, но с совершенно невообразимыми именами!

Правило 2. При раскрытии фигурных скобок никакой сортировки объектов не происходит, и они интерпретируются в том же порядке, в каком указаны внутри фигурных скобок.

Имеется в виду, конечно, не сортировка файлов в алфавитном или ином порядке; команда ls, при помощи которой мы просматриваем содержимое директорий, автоматически сортирует файлы по алфавиту. Также поступает и любой менеджер файлов, захоти мы просмотреть рабочую директория в графическом интерфейсе. Например, команда touch создает файлы в алфавитном порядке, независимо от того, как мы разместим их в фигурных скобках:

$ touch file{d,c,b}.txt

Посмотрим:

$ ls

fileb.txt filec.txt filed.txt

Отключим сортировку в команде ls:

$ ls -U

fileb.txt filec.txt filed.txt

Все равно, файлы создаются в том же порядке.

Правило 2 говорит о другой сортировке - о том, что при раскрытии фигурных скобок, действия над объектами выполняются в том же порядке, в каком они записаны внутри фигурных скобок, и считывание происходит, как и положено, слева направо (в порядке чтения). Вот пример:

$ echo {о,антре,с,}кот
окот антрекот скот кот

Порядок подстановки сохранен, и получившиеся слова сохраняют порядок, в котором их части находились внутри фигурных скобок.

Есть случаи, когда это свойство фигурных скобок приобретает важное значение. Скажем, мы решили отредактировать файл /etc/X11/xorg.conf. Перед этим обычно создают его резервную копию. Мы воспользуемся для этого фигурными скобками.

Только пойдем на подстраховку - чтобы не проводить обучение с реальным файлом /etc/X11/xorg.conf, что может закончиться печально, мы создадим в домашней директории папку Опыт:

$ mkdir Опыт

и сразу перейдем в нее:

$ cd Опыт

Проверим, все ли в порядке:

$ pwd
/home/ya/Desktop/Опыт

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

Итак, создадим файл xorg.conf:

[Опыт]$ touch xorg.conf

Проверим:

[Опыт]$ ls

xorg.conf

Теперь создадим его резервную копию, применяя фигурные скобки:

[Опыт]$ cp xorg.conf{,.bak}

Проверим:

[Опыт]$ ls
xorg.conf xorg.conf.bak

Допустим, наши изменения в файле xorg.conf были неудачны, и мы решили вернуть на его место сохраненную копию. Для этого мы можем применить почти ту же команду, что и для резервного копирования, изменив только последовательность выражений в фигурных скобках:

[Опыт]$ cp xorg.conf{.bak,}
cp: переписать `xorg.conf'? Y

Команда cp запрашивает подтверждения, мы нажимаем ENTER, и дело сделано: файл xorg.conf переписан файлом xorg.conf.bak.

Нужно только не забывать, что шелл интерпретирует команду:

$ cp xorg.conf{.bak,}

как

$ cp xorg.conf.bak xorg.conf.

Поэтому порядок объектов внутри фигурных скобок чрезвычайно важен.

Правило 3. При раскрытии фигурных скобок шелл рассматривает все символы внутри фигурных скобок как простые символы, а не как метасимволы или символы регулярных выражений.

Поэтому, хотя команда

$ rm file*

Удалит из текущей директории все файлы типа file1, file2, fileN, file_file и подобные,

но команда :

$ rm ./file{*,1}

удалит только два файла file* и file1, то есть астериск (*) будет интерпретирован как простая звездочка.

Правило 4. Если нужно поместить внутри фигурных скобок выражения, содержащие фигурные скобки, или запятые, то необходимо экранировать эти символы обратным слэшем (/), а если нужно ввести сам обратный слэш, то его экранируют вторым обратным слэшем:

$ echo Например:{comma-\,,brace-\{,backslash-\\}

Например:comma-, Например:brace-{ Например:backslash-\

Данная статья, как явствует из ее названия, посвящена только применению фигурных скобок в командной строке bash. Они применяются также в скриптах bash, но эта тема далеко выходит за рамки нашего сегодняшнего рассмотрения.

Резюме

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


Работа в командной строке, это искуство, сродни живописи. Посетив сайт художника и увидев его работы, видишь как он вкладывал свои мысль и душу.

Комментариев нет: