Вопрос или проблема
Правильный способ итерации по файлам в каталоге в Bash — использовать “for loop” и шаблон, как показано ниже:
for f in *.jpg; do
echo "- Обработка файла: $f"
done
Но как я могу получить общее количество файлов и текущий индекс итерации цикла? Мне нужно общее количество, а не кумулятивное количество для отображения прогресса.
Я бы сохранил список файлов в массиве, чтобы не считывать файловую систему дважды, что увеличивает производительность и уменьшает потенциальные состояния гонки. Затем используйте другую переменную в качестве индекса.
files=(*.jpg)
total=${#files[@]}
i=0
for f in "${files[@]}"; do
i=$(( i + 1 ))
echo индекс $i
echo всего $total
echo "- Обработка файла: $f"
done
Объяснение
files=(*.jpg)
: сохранить шаблон в массив$files
total=${#files[@]}
: прочитать общее количество в$total
i=0
: инициализировать$i
в 0.i=$(( i + 1 ))
: добавить 1 к$i
с каждой итерацией
Это предполагает, что “первая” итерация равна 1. В зависимости от вашего мнения, возможно, вы захотите начать с 0.
Итерация по индексам
Как предложила Ágatha, мы можем итерировать по номерам индексов. Это гораздо проще. То есть:
files=(*.jpg)
total=${#files[@]}
i=0
for i in "${!files[@]}"; do
echo индекс $i
echo всего $total
echo "- Обработка файла: ${files[$i]}"
done
Объяснение
${!files[@]}
: это расширяется до индексов, а не до содержимого массива. Таким образом, нам не нужно вручную увеличивать счетчик с помощьюi=$(( i + 1 ))
.echo "- Обработка файла: ${files[$i]}"
: однако, вместо того чтобы получать имя файла напрямую из цикла, нам нужно вручную ссылаться на него из массива каждый раз.
Примечание: первый индекс здесь равен 0.
Ответ или решение
Для итерации по файлам в директории и получения индекса и общего количества файлов в Bash существует несколько подходов. Ниже мы рассмотрим два основных метода.
Подход 1: Итерация по массиву файлов
Первый способ — это использование массива для хранения списков файлов с расширением .jpg
и дальнейшая итерация по этому массиву. Это позволяет избежать повторного обращения к файловой системе, что повышает производительность.
Вот пример кода:
files=(*.jpg) # Сохраняем список файлов в массив
total=${#files[@]} # Получаем общее количество файлов
i=0 # Инициализируем счетчик
for f in "${files[@]}"; do # Итерация по массиву
i=$(( i + 1 )) # Увеличиваем индекс на 1
echo "index: $i" # Выводим текущий индекс
echo "total: $total" # Выводим общее количество файлов
echo "- Обрабатываем файл: $f" # Выводим имя обрабатываемого файла
done
Объяснение:
files=(*.jpg)
: Сохраняем все файлы с расширением.jpg
в массивfiles
.total=${#files[@]}
: Получаем общее количество элементов в массивеfiles
.i=0
: Инициализируем переменнуюi
, которая будет использоваться как индекс.i=$(( i + 1 ))
: Увеличиваем индексi
на единицу в каждой итерации цикла.
Подход 2: Итерация по индексам
Другой способ — это итерация непосредственно по индексам массива. Это упрощает код и делает его более лаконичным.
files=(*.jpg) # Сохраняем список файлов в массив
total=${#files[@]} # Получаем общее количество файлов
for i in "${!files[@]}"; do # Итерация по индексам массива
echo "index: $i" # Выводим текущий индекс
echo "total: $total" # Выводим общее количество файлов
echo "- Обрабатываем файл: ${files[$i]}" # Выводим имя обрабатываемого файла
done
Объяснение:
${!files[@]}
: Эта конструкция возвращает индексы массива, что позволяет нам не увеличивать счетчик вручную.echo "- Обрабатываем файл: ${files[$i]}"
: Обращаемся к элементу массива с помощью текущего индексаi
.
Примечание
Первый подход начинается с индекса 1, тогда как второй — с индекса 0. Выбор подхода зависит от ваших предпочтений и задачи.
Таким образом, оба способа обеспечивают возможность итерации по файлам в директории с указанием индекса и общего количества на каждом шаге процесса обработки. Вы можете использовать любой из них в зависимости от вашей ситуации.