mapfile: как загружать вывод команды в массив без while readЕсли результат команды нужно сохранить построчно, часто используют:
items=()
while IFS= read -r line; do
items+=("$line")
done < <(some_command)
В Bash для этого есть встроенный
mapfile.▪️Простой вариант
mapfile -t files < <(find /tmp -type f)
Теперь каждая строка - отдельный элемент массива:
printf '%s\n' "${files[@]}"-t убирает символ переноса строки из каждого элемента.▪️Зачем это лучше
Нет отдельного
while, нет проблемы с subshell и не нужно вручную добавлять элементы:mapfile -t users < <(cut -d: -f1 /etc/passwd)
echo "Users: ${#users[@]}"
Можно обращаться к конкретному элементу:
echo "${users[0]}"▪️Можно читать файл напрямую
mapfile -t lines < config.txt
А затем:
for line in "${lines[@]}"; do
printf 'CONFIG: %s\n' "$line"
done▪️Читать только часть вывода
Например:
mapfile -t -n 10 lines < access.log
В массив попадут только первые 10 строк.
▪️Есть важный нюанс
mapfile ориентирован именно на разделённые строки данные. Если содержимое может содержать \n внутри логического элемента, обычный построчный массив уже не подходит.Для других разделителей можно использовать
-d:mapfile -d ',' -t items < data.txt
Теперь разделителем считается запятая.
▪️Где это удобно
Например, получить список systemd-сервисов:
mapfile -t services < <(
systemctl list-units --type=service --state=running --no-legend |
awk '{print $1}'
)
После этого массив можно безопасно передавать дальше:
for service in "${services[@]}"; do
systemctl is-active "$service"
done▪️Почему это важно
mapfile - встроенный механизм Bash для преобразования потоковых данных в массив. Он делает код короче и избавляет от целого класса проблем, связанных с while read, пайпами и сохранением переменных.BashTex 📱 #bash #linux