Bash цикл по файлам с расширением

Обновлено: 05.07.2024

Как мне в цикле перебрать каждую строку текстового файла с помощью Bash ?

Я использую следующий скрипт:

echo "Start!"

for p in (peptides.txt)

do

echo "$

"

done

Я получаю такой вывод на экране:

Start!

./runPep.sh: line 3: синтаксическая ошибка – неожиданная лексема "('

./runPep.sh: line 3: "for p in (peptides.txt)'

Ответ 1

Один из способов сделать это:

while read p; do

echo "$p"

done <peptides.txt

Данный способ имеет побочные эффекты, заключающиеся в обрезке ведущих пробелов, интерпретации последовательностей обратной косой черты и пропуске последней строки, если в ней отсутствует завершающий перевод строки. Если это не приемл е мо, можно сделать следующее:

while IFS="" read -r p || [ -n "$p" ]

do

printf '%s\n' "$p"

done < peptides.txt

В исключительных ситуациях, если содержимое считывается из стандартного ввода , можно открыть файл, используя другой дескриптор файла:

while read -u 10 p; do

.

done 10<peptides.txt

Здесь 10 - это просто произвольное число (отличное от 0, 1, 2).

Ответ 2

Ответ 3

Еще один способ выполнить данную операцию :

for word in $(cat peptides.txt); do echo $word; done

Этот формат позволяет поместить все это в одну командную строку. Изменяя часть «echo $word», вы можете выполнить несколько команд, разделенных точкой с запятой. В следующем примере содержимое файла используется в качестве аргументов двух других сценариев:

for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done

Или, если вы собираетесь использовать это как редактор потока (используя sed), можно выгрузить вывод в другой файл следующим образом:

for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done > outfile.txt

Если у вас есть пробелы, которые вы не хотите разделять словами/строками, это становится немного сложнее, но та же команда по-прежнему работает следующим образом:

OLDIFS=$IFS; IFS=$'\n'; for line in $(cat peptides.txt); do cmd_a.sh $line; cmd_b.py $line; done > outfile.txt; IFS=$OLDIFS

Этот пример указывает оболочке разделять символы по строкам.

Ответ 4

Еще несколько возможных решений:

Чтение из файла с разделителями

Чтение вывода другой команды с использованием подстановки процесса

Чтение из ввода с разделителями NULL, например , find . -print0

Чтение из более чем одного файла за раз

Чтение всего файла в массив (версии Bash до 4)

while read -r line; do

my_array+=("$line")

done < my_file

Если файл заканчивается неполной строкой (в конце отсутствует новая строка), то:

while read -r line || [[ $line ]]; do

my_array+=("$line")

done < my_file

Чтение всего файла в массив (версии Bash 4x и новее)

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

В прошлый раз мы рассказали об основах программирования для bash. Даже то немногое, что уже разобрано, позволяет всем желающим приступить к автоматизации работы в Linux. В этом материале продолжим рассказ о bash-скриптах, поговорим об управляющих конструкциях, которые позволяют выполнять повторяющиеся действия. Речь идёт о циклах for и while , о методах работы с ними и о практических примерах их применения.

image


Внимание: в посте спрятана выгода!

Циклы for

Оболочка bash поддерживает циклы for , которые позволяют организовывать перебор последовательностей значений. Вот какова базовая структура таких циклов:


В каждой итерации цикла в переменную var будет записываться следующее значение из списка list . В первом проходе цикла, таким образом, будет задействовано первое значение из списка. Во втором — второе, и так далее — до тех пор, пока цикл не дойдёт до последнего элемента.

Перебор простых значений

Пожалуй, самый простой пример цикла for в bash-скриптах — это перебор списка простых значений:


Ниже показаны результаты работы этого скрипта. Хорошо видно, что в переменную $var последовательно попадают элементы из списка. Происходит так до тех пор, пока цикл не дойдёт до последнего из них.



Простой цикл for

Обратите внимание на то, что переменная $var сохраняет значение при выходе из цикла, её содержимое можно менять, в целом, работать с ней можно как с любой другой переменной.

Перебор сложных значений

В списке, использованном при инициализации цикла for , могут содержаться не только простые строки, состоящие из одного слова, но и целые фразы, в которые входят несколько слов и знаков препинания. Например, всё это может выглядеть так:


Вот что получится после того, как этот цикл пройдётся по списку. Как видите, результат вполне ожидаем.



Перебор сложных значений
TNW-CUS-FMP — промо-код на 10% скидку на наши услуги, доступен для активации в течение 7 дней"

Инициализация цикла списком, полученным из результатов работы команды

Ещё один способ инициализации цикла for заключается в передаче ему списка, который является результатом работы некоей команды. Тут используется подстановка команд для их исполнения и получения результатов их работы.


В этом примере задействована команда cat , которая читает содержимое файла. Полученный список значений передаётся в цикл и выводится на экран. Обратите внимание на то, что в файле, к которому мы обращаемся, содержится список слов, разделённых знаками перевода строки, пробелы при этом не используются.



Цикл, который перебирает содержимое файла

Тут надо учесть, что подобный подход, если ожидается построчная обработка данных, не сработает для файла более сложной структуры, в строках которого может содержаться по несколько слов, разделённых пробелами. Цикл будет обрабатывать отдельные слова, а не строки.

Что, если это совсем не то, что нужно?

Разделители полей

Причина вышеописанной особенности заключается в специальной переменной окружения, которая называется IFS (Internal Field Separator) и позволяет указывать разделители полей. По умолчанию оболочка bash считает разделителями полей следующие символы:

  • Пробел
  • Знак табуляции
  • Знак перевода строки

Для того, чтобы решить проблему, можно временно изменить переменную среды IFS . Вот как это сделать в bash-скрипте, если исходить из предположения, что в качестве разделителя полей нужен только перевод строки:


После добавления этой команды в bash-скрипт, он будет работать как надо, игнорируя пробелы и знаки табуляции, считая разделителями полей лишь символы перевода строки.


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



Построчный обход содержимого файла в цикле for

Разделителями могут быть и другие символы. Например, выше мы выводили на экран содержимое файла /etc/passwd . Данные о пользователях в строках разделены с помощью двоеточий. Если в цикле нужно обрабатывать подобные строки, IFS можно настроить так:

Обход файлов, содержащихся в директории

Один из самых распространённых вариантов использования циклов for в bash-скриптах заключается в обходе файлов, находящихся в некоей директории, и в обработке этих файлов.

Например, вот как можно вывести список файлов и папок:


Если вы разобрались с предыдущим материалом из этой серии статей, вам должно быть понятно устройство конструкции if-then , а так же то, как отличить файл от папки. Если вам сложно понять вышеприведённый код, перечитайте этот материал.

Вот что выведет скрипт.



Вывод содержимого папки

Обратите внимание на то, как мы инициализируем цикл, а именно — на подстановочный знак «*» в конце адреса папки. Этот символ можно воспринимать как шаблон, означающий: «все файлы с любыми именами». он позволяет организовать автоматическую подстановку имён файлов, которые соответствуют шаблону.

При проверке условия в операторе if , мы заключаем имя переменной в кавычки. Сделано это потому что имя файла или папки может содержать пробелы.

Циклы for в стиле C

Если вы знакомы с языком программирования C, синтаксис описания bash-циклов for может показаться вам странным, так как привыкли вы, очевидно, к такому описанию циклов:


В bash-скриптах можно использовать циклы for , описание которых выглядит очень похожим на циклы в стиле C, правда, без некоторых отличий тут не обошлось. Схема цикла при подобном подходе выглядит так:


На bash это можно написать так:


А вот рабочий пример:


Этот код выведет список чисел от 1 до 10.



Работа цикла в стиле C

Цикл while

Конструкция for — не единственный способ организации циклов в bash-скриптах. Здесь можно пользоваться и циклами while . В таком цикле можно задать команду проверки некоего условия и выполнять тело цикла до тех пор, пока проверяемое условие возвращает ноль, или сигнал успешного завершения некоей операции. Когда условие цикла вернёт ненулевое значение, что означает ошибку, цикл остановится.

Вот схема организации циклов while
while команда проверки условия
do
другие команды
done

Взглянем на пример скрипта с таким циклом:


На входе в цикл проверяется, больше ли нуля переменная $var1 . Если это так, выполняется тело цикла, в котором из значения переменной вычитается единица. Так происходит в каждой итерации, при этом мы выводим в консоль значение переменной до его модификации. Как только $var1 примет значение 0, цикл прекращается.



Результат работы цикла while

Если не модифицировать переменную $var1 , это приведёт к попаданию скрипта в бесконечный цикл.

Вложенные циклы

В теле цикла можно использовать любые команды, в том числе — запускать другие циклы. Такие конструкции называют вложенными циклами:


Ниже показано то, что выведет этот скрипт. Как видно, сначала выполняется первая итерация внешнего цикла, потом — три итерации внутреннего, после его завершения снова в дело вступает внешний цикл, потом опять — внутренний.



Вложенные циклы

Обработка содержимого файла

Чаще всего вложенные циклы используют для обработки файлов. Так, внешний цикл занимается перебором строк файла, а внутренний уже работает с каждой строкой. Вот, например, как выглядит обработка файла /etc/passwd :


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



Обработка данных файла

Такой подход можно использовать при обработке файлов формата CSV, или любых подобных файлов, записывая, по мере надобности, в переменную окружения IFS символ-разделитель.

Управление циклами

Возможно, после входа в цикл, нужно будет остановить его при достижении переменной цикла определённого значения, которое не соответствует изначально заданному условию окончания цикла. Надо ли будет в такой ситуации дожидаться нормального завершения цикла? Нет конечно, и в подобных случаях пригодятся следующие две команды:

Команда break

Эта команда позволяет прервать выполнение цикла. Её можно использовать и для циклов for , и для циклов while :


Такой цикл, в обычных условиях, пройдётся по всему списку значений из списка. Однако, в нашем случае, его выполнение будет прервано, когда переменная $var1 будет равна 5.



Досрочный выход из цикла for

Вот — то же самое, но уже для цикла while :


Команда break , исполненная, когда значение $var1 станет равно 5, прерывает цикл. В консоль выведется то же самое, что и в предыдущем примере.

Команда continue

Когда в теле цикла встречается эта команда, текущая итерация завершается досрочно и начинается следующая, при этом выхода из цикла не происходит. Посмотрим на команду continue в цикле for :


Когда условие внутри цикла выполняется, то есть, когда $var1 больше 5 и меньше 10, оболочка исполняет команду continue . Это приводит к пропуску оставшихся в теле цикла команд и переходу к следующей итерации.



Команда continue в цикле for

Обработка вывода, выполняемого в цикле

Данные, выводимые в цикле, можно обработать, либо перенаправив вывод, либо передав их в конвейер. Делается это с помощью добавления команд обработки вывода после инструкции done .

Например, вместо того, чтобы показывать на экране то, что выводится в цикле, можно записать всё это в файл или передать ещё куда-нибудь:


Оболочка создаст файл myfile.txt и перенаправит в этот файл вывод конструкции for . Откроем файл и удостоверимся в том, что он содержит именно то, что ожидается.



Перенаправление вывода цикла в файл

Пример: поиск исполняемых файлов

Давайте воспользуемся тем, что мы уже разобрали, и напишем что-нибудь полезное. Например, если надо выяснить, какие именно исполняемые файлы доступны в системе, можно просканировать все папки, записанные в переменную окружения PATH . Весь арсенал средств, который для этого нужен, у нас уже есть, надо лишь собрать всё это воедино:


Такой вот скрипт, небольшой и несложный, позволил получить список исполняемых файлов, хранящихся в папках из PATH .



Поиск исполняемых файлов в папках из переменной PATH

Итоги

Сегодня мы поговорили о циклах for и while в bash-скриптах, о том, как их запускать, как ими управлять. Теперь вы умеете обрабатывать в циклах строки с разными разделителями, знаете, как перенаправлять данные, выведенные в циклах, в файлы, как просматривать и анализировать содержимое директорий.

Bash цикл For

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

В языках сценариев, таких как Bash, циклы полезны для автоматизации повторяющихся задач.

В скриптах Bash есть три базовых конструкции for , while и until .

Стандартный цикл for

for Цикл перебирает список элементов и выполняет данный набор команд.

Цикл Bash for принимает следующую форму:

Список может быть последовательностью строк, разделенных пробелами, диапазоном чисел, выводом команды, массивом и так далее.

Зацикливание строк

В приведенном ниже примере цикл будет перебирать каждый элемент в списке строк, и переменная element будет установлена ​​на текущий элемент:

Цикл выдаст следующий вывод:


Цикл по диапазону номеров

Вы можете использовать выражение последовательности, чтобы указать диапазон чисел или символов, задав начальную и конечную точку диапазона. Выражение последовательности принимает следующую форму:

Вот пример цикла, который перебирает все числа от 0 до 3:

Начиная с Bash 4, также можно указать приращение при использовании диапазонов. Выражение принимает следующую форму:

Вот пример, показывающий, как увеличить на 5:


Цикл на элементах массива

Вы также можете использовать for цикл для перебора массива элементов.

В приведенном ниже примере мы определяем массив с именем BOOKS и выполняем итерацию по каждому элементу массива.

Синтаксис цикла в стиле C

Синтаксис цикла в стиле C for принимает следующую форму:

INITIALIZATION Часть выполняется только один раз , когда начинается цикл. Затем TEST часть оценивается. Если оно ложно, цикл прерывается. Если значение TEST равно true, команды внутри тела for цикла выполняются, а STEP часть обновляется.

В следующем примере кода цикл начинается с инициализации i = 0 и перед каждой итерацией проверяет, является ли i ≤ 10 . Если true, он печатает текущее значение i и [увеличивает переменную] i на 1 ( i++ ), иначе цикл завершается.

Цикл повторяется 1001 раз и выдает следующий результат:

break и continue заявления

break и continue могут быть использованы для управления для выполнения цикла.

break

Оператор break завершает текущий цикл и передает управление программой к инструкции, следующей за прекращено заявление. Обычно используется для завершения цикла при выполнении определенного условия.

В следующем примере мы используем if инструкцию, чтобы завершить выполнение цикла, когда текущий повторяющийся элемент равен «Lithium».

continue

Оператор continue завершает текущую итерацию цикла и передает управление программой к следующей итерации цикла.

В следующем примере мы перебираем диапазон чисел. Когда текущий элемент continue с итерацией равен '2', оператор заставит выполнение вернуться к началу цикла и продолжить следующую итерацию:

Примеры цикла for Bash

Переименование файлов с пробелами в имени файла

В следующем примере показано, как переименовать все файлы в текущем каталоге с пробелом в его именах, заменив пробел подчеркиванием:

Давайте разберем код построчно:

  • Первая строка создает for цикл и перебирает список всех файлов с пробелом в имени. Выражение *\ * создает список.
  • Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя пробел подчеркиванием ( _ ). Часть $ использует расширение параметра оболочки для замены шаблона в параметре на строку.
  • done указывает на конец сегмента цикла.

Изменение расширения файла

В следующем примере показано, как использовать for цикл Bash для переименования всех файлов, заканчивающихся на .jpg в текущем каталоге, заменив расширение файла с .jpg на .jpg.

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

  • Первая строка создает for цикл и просматривает список всех файлов, заканчивающихся на «.jpg».
  • Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя «.jpg» на «.jpg». $ удалить часть «.jpg» из имени файла, используя расширение параметра оболочки
  • done указывает на конец сегмента цикла.


Вывод

Цикл Bash for используется для многократного выполнения заданного набора команд в течение фиксированного числа раз.

Перевод конспекта по bash, который содержит в себе выжимку самых основных возможностей Bourne again shell. Конспект будет полезен любому программисту.



В этом посте автор описал синтаксические конструкции, привел примеры простых сценариев и указал на некоторые подводные камни в bash. Он уверен, что такой конспект обязательно пригодится как начинающим, так и опытным разработчикам, которые могли забыть некоторые особенности этой сверхмощной командной оболочки.

Конвейеры - это команды, которые соединены операторами ; , && , || для выполнения в определенной последовательности. Операторы организации конвейеров работают следующим образом:

  • команда1 ; команда2 - команда2 выполняется после команды1 независимо от результата её работы ;
  • команда1 && команда2 - команда2 выполняется только после успешного выполнения команды1(то есть с кодом завершения 0);
  • команда1 || команда2 - команда2 выполняется только после неудачного выполнения команды1 (то есть код завершения команды1 будет отличным от 0)

В скриптовом языке bash поддерживаются два оператора ветвления: if и case . Оператор if , как и в других языках, выполняет определенный блок указаний, в зависимости от условия. Условие помещают в двойные квадратные скобки [[ . ]] , которые bash рассматривает как один элемент с кодом выхода. Внутри блока операторов помещенных в [[ ]] разрешается использовать операторы && и || . Например:

Обратите внимание, что [ , условие и ] обязательно должны быть разделены пробелами, иначе оболочка воспримет в качестве команды [условие .

Ниже приведена таблица с возможными условиями сравнения:

Если необходимо сделать выбор из нескольких альтернатив, пригодится оператор case. Принцип его работы легче понять на примере:

В примере оператор проверяет значение переменной $extension на совпадение с одним из шаблонов и в случае совпадения выполнит соответствующий блок кода. Если же совпадений не будет, выполнятся указания, соответствующие шаблону * .

Язык оболочки дает пользователю возможность организовывать циклическое выполнение инструкций при помощи циклов: *

while

Оператор while описывается следующим образом:

Интерпретатор в первую очередь выполняет команды, описанные в условии . Если результат выполнения нулевой, то выполняется тело, а после ее выполнения, переход к следующей итерации, в противном случае происходит выход из цикла. В условии может быть любая допустимая команда. Например:

Цикл for выполняет тело для каждого элемента из списка. Синтаксис цикла for таков:

В качестве элементов обычно используют различные шаблоны (wildcards). Очень удобно применять for для прохождения по каталогам и выполнения операций над группой файлов. В примере ниже, цикл проходит по всем файлам с расширением *.bash , перемещает их в директорию

/scripts и добавляет их права на исполнение.

select

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

Пример выше запрашивает у пользователя название пакета, который он желает установить, далее интересуется тем какой пакетный менеджер использовать и в зависимости от выбора устанавливает нужный пакет и останавливает выполнение.
Оболочка также имеет команды, которые изменяют нормальное выполнение цикла. Оператор break полностью останавливает выполнение цикла, оператор continue - переходит к следующей итерации.

В сценариях оболочки возможны объявление и
вызов функций. Стоит отметить, что само понятие функций в bash несколько урезано. На самом деле, функции в bash - это именуемая группа команд, которые выполнятся при обращении к функции. В любом случае функциями следует пользоваться везде, где есть код, повторяющиеся с небольшими вариациями.

Объявление функции имеет следующий вид:

Объявление функции обязательно должно предшествовать ее первый вызов. Обращение к функции происходит путем указания ее имени в качестве команды.
Функция может принимать аргументы и возвращать после своего выполнения результат - код выхода. Функция обращается к своим аргументам точно так же, как и к локальным переменным, с помощью позиционных переменных - $1 , $2 и тд. Результат работы можно возвращать с помощью команды return . Например, функция, которая принимает параметр (имя) и завершает свою работу с кодом 0:

Оболочка дает несколько средств для отладки сценариев. Для активации режима отладки, он должен быть запущен с помощью специальных опций.
Первая строка сценария должна иметь вид:

Можно выбирать среди следующих функций:
–n - читать все команды, но не выполнять их;
–v - выводить все строки по мере их обработки интерпретатором;
*–x - выводить все команды и их аргументы по мере их выполнения.

Для отладки сценария частями, нужный фрагмент отмечают вызовом команды set с помощью соответствующей опции из таблицы. Причем, для включения режима отладки, перед опцией указывают символ - , для отключения режима отладки используют + :

Общая практика отладки заключается в том, чтобы прежде чем запустить ее, необходимо проверить его синтаксис с помощью опции -n . Для большей детальности можно комбинировать ключи -nv . После исправления синтаксических ошибок проводится отладка с помощью опции -x .

Надеюсь вы нашли для себя что-то новое в этом конспекте, или по крайней мере освежили свои знания.

Читайте также: