首页 文章

重新创建目录结构并使用gnu make递归处理每个文件

提问于
浏览
2

我有一个像这样的目录树:

├── dir_a
│   └── file_1.txt
├── dir_b
│   └── dir_c
│       ├── file_2.txt
|       └── file_3.txt
└── file_4.txt

我想镜像此目录结构以保存处理每个文本文件的命令的结果 . 即,输出看起来像这样:

├── build
│   ├── dir_a
│   │   └── processed_file_1.txt
│   ├── dir_b
│   │   └── dir_c
│   │       ├── processed_file_2.txt
│   |       └── processed_file_3.txt
│   └── processed_file_4.txt
├── dir_a
│   └── file_1.txt
├── dir_b
│   └── dir_c
│       ├── file_2.txt
|       └── file_3.txt
└── file_4.txt

我不是很擅长Makefile,所以我的问题是:我怎样才能获得一个Makefile来重新创建目录结构并递归处理所有文本文件以将它们放在构建目录中的正确位置?当输入文件发生变化时,我将重复运行,因此不处理未更改文件的Makefile似乎是正确的方法 .

更新:我还应该提到经常添加新的输入文件,所以我不希望Makefile明确地命名它们 .

2 回答

  • 2

    如果您使用具有不同后缀的词干而不是插入“processed_”字符串会更容易,但这里有一个适用于我的示例:

    OUTPUTS := build/dir_a/processed_file_1.txt       \
               build/dir_b/dir_c/processed_file_2.txt \
               build/dir_b/dir_c/processed_file_3.txt \
               build/processed_file_4.txt
    
    all: $(OUTPUTS)
    
    .SECONDEXPANSION:
    $(OUTPUTS): build/% : $$(subst processed_file_,file_,%)
        mkdir -p $(dir $@)
        cp $< $@
    
    clean:
        rm -rf build
    

    您可以通过更改文件名的结尾而不是开头来删除 .SECONDEXPANSION 的复杂性:

    OUTPUTS := build/dir_a/file_1.out       \
               build/dir_b/dir_c/file_2.out \
               build/dir_b/dir_c/file_3.out \
               build/file_4.out
    
    all: $(OUTPUTS)
    
    $(OUTPUTS) : build/%.out : %.txt
        mkdir -p $(dir $@)
        cp $< $@
    
    clean:
        rm -rf build
    
  • 0

    正如卡尔建议的那样,你可以使用secondary expansion,但结合order-only先决条件 .

    BUILD_DIR = build
    
    IN_FILES := dir_a/file_1.out       \
                dir_b/dir_c/file_2.out \
                dir_b/dir_c/file_3.out \
                file_4.out
    
    OUT_FILES := $(IN_FILES:%=$(BUILD_DIR)/%)
    
    all: $(OUT_FILES)
    
    .SECONDEXPANSION:
    $(OUT_FILES) : $(BUILD_DIR)/%.out : %.txt | $$(@D)/.
        # your text processing rule here...
    
    %/. :
        mkdir -p $*
    

    | $$(@D) 表示:

    在二次扩展期间

    • 计算 $(@D) automatic variable(目标的目录部分)的值,并且

    • 添加对它的依赖顺序依赖,即确保目录存在,但如果目标比目录旧,则不考虑重新构建目标(这通常是一种情况)

相关问题