Программы
Как на Bash посчитать число строк в проекте (директории)

Как на Bash посчитать число строк в проекте (директории)

Ниже будет представлен однострочник, решающий данную задачу на Bash + пошаговое описание его работы.

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

Код ниже пройдётся по всем вложенным в текущую директорию файлам, посчитает количество строк, сложит вместе и выведет на консоль:

    find -type f -name \*.c -exec wc -l {} \; \
      | cut -d' ' -f1 \
      | while read line; do \
          res=$(($res + $line)); \
          echo $res; \
        done \
      | tail -1

Для удобства я его отформатировал, а чтобы Bash не замечал переводы строк - заэкранировал их символом \.

Начнём с первой строки:

    find -type f -name \*.c -exec wc -l {} \;

С помощью утилиты find можно рекурсивно пробежаться по директории в поисках нужных файлов. Так, к примеру, сейчас мы ищем по типу "f" - файлы (-type f), имя которых заканчивается на "*.c" (-name \*.c). При чём символ "*" нам нужно экранировать, ведь иначе Bash попытается подставить аргументом файлы, подходящие под шаблон. В нашем случае - *.с.

С помощью же ключа -exec мы также просим find для каждого файла выполнить команду. В нашем случае используем утилиту wc - wc -l - посчитать строки:

    $ find -type f -name \*.c -exec wc -l {} \;
    38 ./t/test_x.c
    45 ./t/test_y.c
    49 ./t/test_z.c
    224 ./main.c
    267 ./inc/x.c
    38 ./inc/y.c
    77 ./inc/z.c
    ...

Теперь мы имеем 2 колонки, разделённые пробелом: количество строк, имя файла.

Вторая колонка нам неинтересна, поэтому вырежем её утилитой cut:

    cut -d' ' -f1

Устанавливаем разделителем пробел (-d' '), оставляем 1-ую колонку (-f1).

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

На данный момент наши данные приняли вид:

    $ find -type f -name \*.c -exec wc -l {} \; | cut -d' ' -f1
    38
    45
    49
    224
    267
    38
    77
    ...

Теперь нам нужно просуммировать строки. И здесь нам потребуется цикл while. Считываем строчку за строчкой, а в теле цикла суммируем их и выводим результат:

    res=$(($res + $line)); \
    echo $res; \

Теперь в последней строке вывода будет искомое число. Получаем его утилитой tail. Ключ указывает на то, сколько строк с конца мы хотим получить: tail -1 - получить последнюю строку.

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

Изображение Выучи 10 хороших привычек для работы в UNIX от IBM