Составные списки команд интерпретатора Linux: циклы

Последний важный вид составных списков предназначен для многократного циклического выполнения команд в сценариях командного интерпретатора. Различают цикл с параметром, реализуемый конструкцией

for name in [words …]; do list; done

и циклы о, условием «ПОКА»

while [!] list; do list; done

и «ДО»

unitl [!] list do list; done

с ключевыми словами for, in, while, until, do, done, соответственно.

В примере из листинга ниже цикл с параметром используется для создания галерея миниатюр фотографий при помощи составного списка for и подстановки вывода команд.

В режиме трассировки команд интерпретатора видно, что команда convert в теле цикла выполняется столько раз, сколько слов (найденных имен файлов) было подставлено из вывода команды find.

При этом переменная file на каждой итерации цикла принимает очередное значение из подставленного списка. В результате последовательных подстановок разных значений переменной $file были выполнены одинаковые преобразования разных файлов изображений.

Цикл с параметром: создание галереи миниатюр фотографий

bender@ubuntu:~$ set -x

bender@ubuntu:~$ for file in $(find DCIM -name ‘*.jpg’) ↵
> do ↵
> convert $file -resize 100x $(basenane $file .jpg).mini.jpg ↵

done ↵

++ find DCIM -iname ‘*.jpg’

+ for file in ‘$(flnd DCIM -name ‘\’ ‘*.jpg’\»)’

++ basename DCIM/DSC_0067.jpg .jpg

+ convert DCIM/DSC_0067.jpg -resize 100x DSC_0067.mini.jpg

+ for file in ‘$(find DCIM -name ‘\»*.jpg’ \ ‘ ‘)’

++ basename DCIM/DSC_0189.jpg .jpg

+ convert DCIM/DSC_0189.jpg -resize 100x DSC_0189.mini.jpg

+ for file in ‘$(find DCIM -iname ‘\’ ‘. *jpg’\»)’

++ basename DCIM/DSC_0062.jpg .jpg

+ convert DCIM/DSC_0062.jpg -resize 100x DSC_0062.mini.jpg

В этом примере для формирования результирующих имен файлов используется подстановка вывода команды basename для отрезания «расширений» .jpg от имен файлов, к которым затем приклеиваются новые «расширения» .mini.jpg.

В примере из листинга ниже составной список for используется вместе с подстановкой команды seq, формирующей список чисел 1,…, 254, очередные значения из которого принимает переменная node. На каждой итерации цикла используется подстановка значения $node для формирования IP-адреса очередного узла локальной сети, доступность которого проверяется при помощи команды ping.

Цикл с параметром: проверка доступности узлов локальной сети

bender@ubuntu:~$ for node in $(seq 1 254) ↵

>do ↵

> ping -с 1 -W 1  192.168.1.$node ↵

> done ↵

++ seq 1 254

0 + for node in *$(seq 1 254)’

+ ping -с 1 -W 1 192.168.1.1 4

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.

— 192.168.1.1 ping statistics —

1 packets transmitted, 0 received, 100% packet loss, time 0ms

+ for node in ‘$(seq 1 254)’-

+ ping -с 1 -W 1 192.168.1.45

PING 192.168.16.45 (192.168. 16.45) 56(84) bytes of data.

64 bytes from 192.168.16.45: icmp_req=l ttl=62 time=5.25 ms

— 192.168.16.45 ping statistics —

1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 5.257/5.257/5.257/0.000 ms

+ for node in ‘$(seq 1 254)’

+ ping -c 1 -W 1 192.168.1.254

PING 192.168.1.1 (192.168.1.254) 56(84) bytes of data.

— 192.168.1.254 ping statistics —

1 packets transmitted, 0 received, 10096 packet loss, time 0ms

В примере из листинга ниже на основе составного списка while организован «индикатор прогресса» процесса фонового сжатия ISO-образа диска при помощи опроса его состояния. Цикл выполняется, пока успешна команда ps, опрашивающая процесс, PID которого передан при помощи подстановки специального параметра $!. При каждой итерации цикла команда ls выводит размер выходного файла dvd.iso.bz2, а команда sleep приостанавливает выполнение на 1 секунду.

Цикл «ПОКА»: ожидание завершения процесса

bender@ubuntu:~$ bzip2 -kf dvd.iso &
[1] 5773

bender@ubuntu:~$ set -x

bender@ubuntu:~$ while ps p $! ; do ls -Ih dvd.iso.bz2; sleep 1 «done

+ ps p 5773

PID   TTY       STAT    TIME    COMMAND

5773    pts/0   R           0:05       bzip2 -kf dvd.iso
+ ls —color=auto -lh dvd.iso.bz2
-rw 1  bender  bender 9,6M  дек. 12 13:38 dvd.iso.bz2
+ sleep 1 О + ps p 5773

PID   TTY        STAT    TIME   COMMAND
5773    pts/0    R          0:58       bzip2 -kf dvd.iso
+ ls —color=auto -lh dvd.iso.bz2
-rw——- 1  bender  bender 87M  дек. 12 13:39 dvd.iso.bz2
[1]+ Готово                             bzip2 -kf dvd.iso
+ sleep 1

+ ps p 4523
PID   TTY        STAT    TIME   COMMAND

В примере из листинга ниже составной список while используется в качестве генератора пар имен файлов для массового параллельного переименования. Для этого стандартный поток ввода построчно считывается в цикле при помощи встроенной команды интерпретатора read, причем на каждой итерации цикла переменная FN принимает значение очередной строки, а команда read завершается успешно до исчерпания строк.

В результате выполнения встроенной команды echo и при помощи подстановки значения переменной SFN и подстановок вывода команд dirname и basename на стандартном потоке вывода составного списка формируются пары имен файла — исходное считанное путевое имя и синтезированное путевое имя с измененным «расширением файла».

Исходный поток имен формируется командой find, а результирующий поток передается команде xargs, которая в свою очередь передает пары имен (-n2) командам mv, запускаемым параллельно в количестве ядер процессора,- которое было получено командой nproc.

Цикл «ПОКА»: массовое параллельное переименование файлов

bender@ubuntu:~$ find DCIM -name ‘*.jpg’ | ↵
> while read FN ; do echo $FN $(dirname $FN)/$(basenane $FN .jpg).jpeg ; done | ↵
> xargs -n2 -P $(nproc) mv ↵

Аналогично, в примере из листинга ниже составной список while используется в качестве генератора классификатора файлов по их контрольном MDS-суммам.

При помощи команд find, xargs и md5sum формируется поток строк, в первом столбце которых будет выведена контрольная сумма W:[MD5] файла, а во втором столбце— его имя.

Полученный поток построчно считывается в цикле при помощи встроенной команды интерпретатора read, причем на каждой итерации переменные sum и file принимают значения соответственно первого и второго столбцов строки, при этом во временном каталоге создаются файлы классификатора, именованные значениями $sum, в содержимое которых добавляются имена $file.

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

Для поиска па классификатору используется аналогичная связка find, xargs и wc, формирующая на потоке вывода текстовую таблицу по два столбца в строке, в первом из которых указано количество строк в файле классификатора, а во втором — его имя.

Затем, при помощи процессора текстовых таблиц awk на стандартный поток вывода печатаются только те имена файлов классификатора( из второго столбца строк таблицы (print $2), в первом столбце которых содержится число, большее единицы ($1 > 1). Полученный поток имен файлов отправляется на xargs для вывода имен (-t) и «одержимого при помощи cat. Необходимо заметить, что сам классификатор размещен в каталоге файловой системы W:[tmpfs], использующей для хранения оперативную память, и имеет случайное имя, сгенерированное при помощи mktemp.

Цикл «ПОКА»: поиск дублирующихся фотографий

bender@ubuntu:~$ df -h /run/shm\

Файл.система      Размер    Использовано    Дост   Использовано%   Смонтировано в
none                       4,0G         26М                        3,9G   1%                            /run/shm

medoff@ubuntu:~$ findmnt /run/shm

TARGET         SOURCE    FSTYPE   OPTIONS

/run/shm                            tmpfs rw,nosuid,nodev,relatime

bender@ubuntu:-r$ T=$(mktemp -d /run/shm/XXXXXX)

bender@ubuntu:~$ find DCIM -type f -printO | xargs -0 -n1 md5sum |↵

> while read sum file ; do echo $file >> $T/$sum ; done↵

bender@ubuntu:~$ find $T -type f | xargs -n1 wc -l |↵
>awk ‘$1 > 1 { print $2 }’ | xargs -nl -t cat

cat /dev/shm/fjYfn/4f7bal91573ded309bc0f04e08309d8a

DCIM/Camera/IMG_20140731_212625+.jpg

DCIM/Camera/IMG_20140731_212625.jpg

cat /dev/shm/fjYfn/4329ae8006b6935d0c7fd66b57e07c0c

DCIM/DSC_0046+.3PG

DCIM/DSC_0046.JPG

В листинге ниже проиллюстрирована вторая форма цикла с условием — составной список until, который используется для ожидания доступности подключения к Интернету путем опроса наличия связи с узлом 8.8.8.8 (публичный DNS-сервер компании Google) при помощи команды ping. Нужно отметить, что использование until list do … ;  done может быть заменено эквивалентным while ! list do …; done с указанием признака отрицания !.

Цикл «ДО»: ожидание доступности подключения к Интернету

bender@ubuntu:~$ set -x

bender@ubuntu:~$ until ping -c1 -w1 8.8.8.8 ! do sleep 1;date ; done

+ ping -c1 -w1 8.8.8.8

connect: Network is unreachable

+ sleep 1

+ date

C6. дек. 19 09:11:32 MSK 2018

+ ping -d -w1 8.8.8.8

connect: Network is unreachable

+ sleep 1

+ date

Сб. дек. 19 09:11:39 MSK 2018

+ ping -cl -wl 8.8.8.8

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

64 bytes from 8.8.8.8: icmp_req=1 ttl=56 time=11.6 ms

— 8.8.8.8 ping statistics —

1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 11.670/11.670/11.670/0.000 ms

 

Добавить комментарий