Я использую Bash на Ubuntu и GNU Make 4.2.1.

Я пытаюсь написать Makefile, который будет выполнять простые операции с некоторыми данными (файлы .TXT), которые у меня есть. Мои разные файлы .TXT хранятся в 3 каталогах data/dir1 , data/dir2 и data/dir3.

Например, я хотел бы ввести make count_dir1, make count_dir2 или make count_dir3, чтобы получить общее количество строк в каталоге.

Без использования Makefile я знаю, как это сделать, если, допустим, мой текущий каталог — data/dir1 :

find . -name '*.TXT*' -type f | xargs wc -l

Я получаю количество строк в каждом файле и общую сумму, что мне и нужно.

Теперь, на данный момент, мои цели в основном выглядят так:

count_dir1: /home/data/dir1
    @cd /home/data/dir1 &&\
    find . -name '*.TXT*' -type f | xargs wc -l


count_dir2: /home/data/dir2
    @cd /home/data/dir2 &&\
    find . -name '*.TXT*' -type f | xargs wc -l

count_dir3: /home/data/dir3
    @cd /home/data/dir3 &&\
    find . -name '*.TXT*' -type f | xargs wc -l

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

dirs = /home/data/dir1 /home/data/dir2 /home/data/dir3

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

Заранее спасибо ! :)

-1
Alex 21 Авг 2020 в 13:45
У вас есть подкаталоги ниже data/dir1 и т. д.? Если нет, то wc -l data/dir1/*.TXT* будет достаточно для подсчета для первого каталога. Если у вас много тысяч файлов, это, очевидно, не сработает, как и ваше решение find (общее количество строк будет неправильным, поскольку wc будет вызываться несколько раз).
 – 
Kusalananda
21 Авг 2020 в 14:32
Нет, никаких подкаталогов!
 – 
Alex
21 Авг 2020 в 15:39

1 ответ

Лучший ответ

Если gmake достаточно совместим со стандартами, вы можете использовать:

DIRS= /home/data/dir1 /home/data/dir2 /home/data/dir3

.PHONY: $(DIRS)

all: $(DIRS)

$(DIRS):
        cd $@ && find . -name '*.TXT*' -type f -exec wc -l {} +

.PHONY: необходим, так как каталоги существуют и не зависят от других целей.

Использование xargs с find устарело, так как в 1988 году был введен execplus.

Если вам нравятся сокращения для длинных имен целей, вы можете добавить

count1: /home/data/dir1

count2: /home/data/dir2

count3: /home/data/dir3

В ваш make-файл.

0
schily 21 Авг 2020 в 15:29
Итак, как бы я назвал свои цели? Например, мне пришлось бы набирать make /home/data/dir1 ? Есть ли способ набрать make count1, который будет вызывать make /home/data/dir1 как псевдоним, я полагаю?
 – 
Alex
21 Авг 2020 в 15:20
Когда я вызвал make /home/data/dir1, он вернул «сделать /home/data/dir1 уже обновленным», что я получаю, но я просто хотел, чтобы мне что-то напечатали, а не файл, который нужно создать, чтобы это сообщение не помощь ! Кроме того, я только что увидел ваше редактирование и попытался вызвать make count 1, но затем у меня было make: Nothing to be done for 'count1' (угадайте, что Makefile видит count1 в качестве цели без каких-либо правил?
 – 
Alex
21 Авг 2020 в 15:35
Значит, вы забыли добавить строку .PHONY: ... в make-файл, или ваша версия gmake не работает.
 – 
schily
21 Авг 2020 в 15:44
Упс, это плохо, я не понимаю, почему я изменил свой .PHONY: на .PHONY= . Большое спасибо :)
 – 
Alex
21 Авг 2020 в 15:47
Также для дальнейших целей, как я могу использовать DIRS в качестве зависимостей и вызывать один из каталогов в зависимости от моей цели, например, если моя цель subset_dir2, и я хочу ссылаться на /home/data/dir2 соответственно в моем правило?
 – 
Alex
21 Авг 2020 в 16:15