Последний важный вид составных списков предназначен для многократного циклического выполнения команд в сценариях командного интерпретатора. Различают цикл с параметром, реализуемый конструкцией
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