gpt4 book ai didi

linux - Makefile创建子目录并通过ID列表的文件下载一些文件

转载 作者:太空宇宙 更新时间:2023-11-04 12:37:23 25 4
gpt4 key购买 nike

描述

我正在编写 GNU make Makefile 以从服务器下载一些文件(L1.txt、L2.txt、...)。我有一个目标来制作它们中的每一个或全部。

每个文件由 ID 列表组成。

对于每个列表文件 (L1.txt, L2.txt, ...) 我想创建一个与列表文件同名的子目录 (ex, L1.txt -> ./L1, .. ) - 简单 :).

然后对于每个列表文件,对于列表文件中的每个 ID,我想将其他文件下载到特定目录(由列表文件创建的目录)并处理它以生成一些二进制文件。每个子目录中的所有二进制文件都应聚合到其他 .merged.bin - 复杂 :/

例子

L1.txt:

10, 20, 30

L2.txt:

101, 102, 105

所以在 make 之后我想要:

./L1.merged.bin
./L2.merged.bin
./conf/L1.txt
./conf/L2.txt

./data/L1/10.txt
./data/L1/20.txt
./data/L1/30.txt
./data/L1/10.bin
./data/L1/20.bin
./data/L1/30.bin

./data/L2/101.txt
./data/L2/102.txt
./data/L2/105.txt
./data/L2/101.bin
./data/L2/102.bin
./data/L2/105.bin

示例代码

LIST_FILES=$(wildcard conf/*.txt)
LIST_FOLDERS=$(patsubst conf/%.txt, data/%, ${LIST_FILES})
MERGED_FILES=$(patsubst conf/%.txt, %.merged.bin, ${LIST_FILES})

all: mergesubs


mergesubs: ${MERGED_FILES}

conf/%:
curl -sSL some-list-url/$*.txt > $@

data/%: conf/%.txt
test -d $@ || mkdir $@

# PSEUDO CODE STARTS HERE:
# template code to understand inner-workings.
# should not work as target should be made for each data sub directory.
data/*/%.bin: data/*/%.txt
my_process $< > $@

data/*/%.txt:
curl -sSL someurl/$* > $@

# PROBLEMS START HERE!
# prerequisite should be a list of files,
# with file extension .bin and generated from list file
# provided before. conf/L1.txt might be not downloaded
# so I need to add it to prerequisites,
# but make does not provide ordering for prerequisites
# Something similar
%.merged.bin: $(shell cat conf/%.txt) conf/%
cat $^ > $@

问题

如何为这种情况编写依赖树?我想保留所有 gnu make 的优点:只下载一次文件,只处理一次等等。

附言

请不要推荐除 GNU Make 之外的其他工具,因为我需要在 linux 环境中使用 Makefile 执行此操作。

最佳答案

在您阅读我的代码之前的几点评论:

不要使用 $(wildcard) - 这是个坏主意。列出您期望的项目,就像我在 LIST_FILE_STEMS

中所做的那样

附加 /. 是告诉 Make 这是一个目录的好方法(仅附加 / 是不够的 - Make 去掉它)。但是,我在这里为 %/. 制定规则的方式只对父级存在时创建的目录可靠地工作。这是因为 mkdir -p 与父目录存在微妙的竞争条件。在您的情况下,您只创建一级目录,所以没问题。

当下载远程文件时,依赖远程文件是没有意义的,因为如果不先下载它就无法确定它的时间戳。所以在这种情况下,我在这里所做的一种好方法是仅在本地副本不存在时才下载。如果要强制重新下载,则必须先删除本地副本。

任何重要的配方都应该依赖于Makefile,因此如果配方发生变化,目标就会重建。

我在这里使用了一些微妙的技术,如果您没有经验,在阅读代码时不会立即显而易见。但是当您尝试更改代码时,它可能会“停止工作”,因为您没有意识到发生了什么。那将是你在那个时候学习的机会——GNU Make 手册是你的 friend :) 所以这就是为什么我没有特别注释代码的原因。

请记住在尝试我的代码之前用食谱中的前导制表符替换空格 - 据我所知,无法在 Stack Overflow 的代码中粘贴制表符 - 它将制表符更改为空格。

给你:

LIST_FILE_STEMS := \
L1 \
L2 \

LIST_FILES := $(patsubst %, conf/%.txt, $(LIST_FILE_STEMS))

MERGED_FILES := $(patsubst conf/%.txt, %.merged.bin, $(LIST_FILES))

GENERATED_MAKEFILES := $(addsuffix _Makefile, $(LIST_FILE_STEMS))

all: $(MERGED_FILES)

-include $(GENERATED_MAKEFILES)

$(GENERATED_MAKEFILES): %_Makefile: conf/%.txt Makefile
echo $*.merged.bin: $(patsubst %, data/$*/%.bin, $(shell sed 's/,//g' < $<)) > $@

%.merged.bin:
cat $^ > $@

$(LIST_FILES): Makefile
curl -sSL $(subst conf,some-list-url,$@) > $@

%/.:
mkdir -p $@

.SECONDEXPANSION:

%.bin: %.txt Makefile | $$(dir $$@).
my_process $< > $@

data/%.txt: Makefile | $$(dir $$@).
curl -sSL someurl/$(notdir $*).txt > $@

关于linux - Makefile创建子目录并通过ID列表的文件下载一些文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41271175/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com