Утилитарная задача: прочесть текстовый файл, что-то поделать с его содержимым и вывести результаты в виде пронумерованных строк.
Пример реально работающего скрипта. Есть набор нумерованных каталогов, есть файл, в котором каждому номеру сопоставлена текстовое описание. Чтобы пользователям не вспоминать, чему соответствует какой номер, хочу создать симлинки на номерные каталоги в виде человеко-читаемых названий.
Структура файла данных
Где NNN - трехзначное число. Если меньше 100, то дополненное ведущими нулями, хотя можно обойтись и без этого. (ведущие нули, кстати, сыграли злую шутку вроде той, о которой я уже писал в "особенностях арифметики")
Задача: пройтись по файлу и для всех существующих каталогов с номерными именами создать симлинки из текстовой части. Номеров в списке больше, чем существующих каталогов, поэтому создавать каталоги, которых сейчас не существует, не надо.
Пример реально работающего скрипта. Есть набор нумерованных каталогов, есть файл, в котором каждому номеру сопоставлена текстовое описание. Чтобы пользователям не вспоминать, чему соответствует какой номер, хочу создать симлинки на номерные каталоги в виде человеко-читаемых названий.
Структура файла данных
/var/samba/secret/work
(файл был несколько причёсан из исходного сырья):NNN Текст[;]
Где NNN - трехзначное число. Если меньше 100, то дополненное ведущими нулями, хотя можно обойтись и без этого. (ведущие нули, кстати, сыграли злую шутку вроде той, о которой я уже писал в "особенностях арифметики")
Задача: пройтись по файлу и для всех существующих каталогов с номерными именами создать симлинки из текстовой части. Номеров в списке больше, чем существующих каталогов, поэтому создавать каталоги, которых сейчас не существует, не надо.
#!/bin/bash
while read
do
a=$[a+1]
deptSA=`echo "$REPLY"|cut -d \ -f 2-|sed "s/\;//"`
depNSA=${REPLY:0:3}
printf "%02d:%03d:$deptSA\n" $a $[10#$depNSA]
if [ -d /var/samba/secret/$depNSA ]
then
ln -s /var/samba/secret/$depNSA /var/samba/secret/"$deptSA"
fi
done</var/samba/secret/work
Файл будем читать построчно в цикле
while
командой read
. Мне лень изощряться, поэтому читаем из stdin
, куда файл вливается через переназначение. Вдвойне лень изощряться, поэтому не присваиваю никакую переменную, а использую дефолтную $REPLY
.По-хорошему, переменную-счётчик $a надо бы обнулить перед началом цикла, но задача не критичная и можно положиться на bash, который передает чистое окружение вызываемому процессу.
Для новичков сразу обращу внимание вот на что:
1. в левой части оператора присваивания переменная используется без знака доллара
2. если переменная фигурирует в вычисляемом выражении внутри $(...) или $[...], доллар тоже не нужен. (а вообще, кому он нужен кроме ФРС США?)
Итак, для каждой прочитанной строки выполняются следующие действия:
Выделяем два компонента: в переменную
$deptSA
попадает текстовое описание каталога, а в переменную $depNSA
- номер.Способов выделить эти компоненты много, я воспользовался первыми, которые пришли в голову. Номер - три цифры, прижатые к началу строки - выделяется очень просто - берем 3 символа, начиная с нулевого. Для текстового компонента (с 5 символа до конца строки) я решил извратиться и воспользоваться командой
cut
.Ключ -d задает разделитель полей, именно поэтому после "\" стоят два пробела - первый из них выступает в роли "параметра" для "\". Для наглядности можно было написать "\ ", но два пробела выглядят загадочнее.
Комбинация
-f 2-
выводит "начиная со второго поля и до конца строки". По сути, раз поля отделяются пробелом, то будет выведено всё, что есть в строке сразу после номера и стоящего за ним пробела-разделителя.Поскольку в конце текстового описания может быть, а может и не быть точка с запятой, то отрезаем ее с помощью
sed
.Команда
printf
- вывод строки с форматированием - знакома многим, имеющим дело с C-подобными языками. Она берет первым параметром строку форматирования и выводит, согласно оной, последующие параметры. Как раз при выводе номерного имени каталога вылезла бяка, о которой я упоминал в начале статьи: из-за ведущих нулей printf
воспринимает ее как восьмеричное число и выпадает в осадок, хорошо хоть не в kernel panic, когда в "восьмеричном" числе обнаруживает цифры 8 и 9. Поэтому пришлось переменную $depNSA
принудительно объявлять десятичной.Использованная мной строка форматирования выводит первый параметр (
$a
- номер обрабатываемой строки) как десятичное число с двумя знаками, при необходимости - с ведущим нулём, через двоеточие второй параметр - номер каталога - как десятичное с тремя знаками и ведущими нулями, ну и интерпретатор подставляет туда же через еще одно двоеточие значение текстового описания, переменную $deptSA
: она не содержит символов процента, поэтому просто выводится командой printf
как есть.Впрочем, этот этап интересен только как пример работы с форматированным выводом, и в данном скрипте используется только для красоты.
Проверяется существование каталога с таким именем-номером, чтобы не создавать симлинк на несуществующий каталог.
Наконец, создается собственно символическая ссылка с именем из переменной
$deptSA
на каталог с именем из переменной $depNSA
.В итоге имеем набор каталогов, в каждый из которых можно зайти хоть так, хоть этак. В отличие от ярлыков, создаваемых Windows, симлинки в "проводнике" выглядят и ведут себя как полноценные каталоги. То есть, не возникает путаница, когда переходишь в каталог "Тарам-пам-пам", а оказываешься в каталоге "666".
Комментариев нет:
Отправить комментарий
Пожалуйста, воздержитесь от грубостей и персональных нападок.
Я не против матерщины, но она должна быть уместной и использоваться для выражения эмоций, а не в качестве основного средства выражения мыслей.