首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在makefile中正确使用gzip?

如何在makefile中正确使用gzip?
EN

Stack Overflow用户
提问于 2014-10-24 17:13:36
回答 2查看 2.2K关注 0票数 0

我是make新手,所以可以随意更正我对这个问题的语法。

我想要创建一个makefile来下载一堆压缩文件,解压缩它们并对它们做一些事情。这是我的玩具例子:

代码语言:javascript
复制
my_dir/*.txt.gz:
    echo "# obtaining data"
    mkdir -p my_dir
    echo 1 > my_dir/file1.txt
    gzip my_dir/file1.txt
    echo 2 > my_dir/file2.txt
    gzip my_dir/file2.txt

my_dir/*.txt: my_dir/*.txt.gz
    echo "# unzipping data"
    parallel gzip -d ::: my_dir/*.txt.gz

final.txt: my_dir/*.txt
    echo "# doing something with data"
    cat my_dir/*.txt > $@

clean_my_dir:
    rm -rf my_dir
    rm -f final.txt

当我运行make final.txt时,我得到了我期望的结果(final.txt包含1\n2),但是如果我再次运行make final.txt (没有运行make clean_my_dir),就会得到一个错误:

代码语言:javascript
复制
make final.txt
echo "# obtaining data"
# obtaining data
mkdir -p my_dir
echo 1 > my_dir/file1.txt
gzip my_dir/file1.txt
echo 2 > my_dir/file2.txt
gzip my_dir/file2.txt
echo "# unzipping data"
# unzipping data
parallel gzip -d ::: my_dir/*.txt.gz
echo "# unzipping data"
# unzipping data
parallel gzip -d ::: my_dir/*.txt.gz
gzip: can't stat: my_dir/*.txt.gz (my_dir/*.txt.gz.gz): No such file or directory
make: *** [my_dir/file2.txt] Error 1

我确信我在设置目标和先决条件的方式上犯了错误:我希望final.txt包含file1.txtfile2.txt的内容,但这些文件最初是压缩的。当有压缩文件时,我如何告诉make调用gzip,在未压缩文件可用时不做任何事情?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-24 19:39:25

经过一些实验,我创建了下面的makefile:

代码语言:javascript
复制
COMPRESSED_DIR = my_dir
UNCOMPRESSED_DIR = temp_dir

DEPS = \
    $(UNCOMPRESSED_DIR)/file1.txt \
    $(UNCOMPRESSED_DIR)/file2.txt

##
##  Recipes how to obtain compressed files
##  (may propably not so trivial in your intended application)
##
$(COMPRESSED_DIR)/file1.txt.gz: 
    @echo ""
    @echo "# obtaining $@"
    mkdir -p $(COMPRESSED_DIR)
    echo 1 > $(COMPRESSED_DIR)/file1.txt
    gzip $(COMPRESSED_DIR)/file1.txt

$(COMPRESSED_DIR)/file2.txt.gz: 
    @echo ""
    @echo "# obtaining $@"
    mkdir -p $(COMPRESSED_DIR)
    echo 2 > $(COMPRESSED_DIR)/file2.txt
    gzip $(COMPRESSED_DIR)/file2.txt

## or alternatively:
#$(COMPRESSED_DIR)/%.txt.gz: 
#   @echo ""
#   @echo "# obtaining $@"
#   mkdir -p $(COMPRESSED_DIR)
#   echo $* > $(COMPRESSED_DIR)/$*.txt
#   gzip $(COMPRESSED_DIR)/$*.txt

##
##  Recipe to unpack compressed files
##
$(UNCOMPRESSED_DIR)/%.txt: $(COMPRESSED_DIR)/%.txt.gz
    @echo ""
    @echo "# unpacking $<..."
    mkdir -p $(UNCOMPRESSED_DIR)
    gzip -c -d $< > $@

##
##  Recipe to make final.txt
##
final.txt: $(DEPS)
    @echo ""
    @echo "# doing something with data"
    cat $(UNCOMPRESSED_DIR)/*.txt > final.txt

##
##  Recipe to clean
##
clean:
    rm -rf $(COMPRESSED_DIR)
    rm -rf $(UNCOMPRESSED_DIR)
    rm -f final.txt

正如前面指出的,gzip删除txt.gz文件,因此,如果再次生成final.txt,将重新执行创建txt.gz文件的配方。

我所做的是将解压缩的txt.gz文件放在单独的目录中,并强制gzip在解压缩时保留原始文件。这将导致以下行为:

如果第一次调用,将创建和解压缩txt.gz文件,并创建final.txt:

代码语言:javascript
复制
# obtaining my_dir/file1.txt.gz
mkdir -p my_dir
echo 1 > my_dir/file1.txt
gzip my_dir/file1.txt

# unpacking my_dir/file1.txt.gz...
mkdir -p temp_dir
gzip -c -d my_dir/file1.txt.gz > temp_dir/file1.txt

# obtaining my_dir/file2.txt.gz
mkdir -p my_dir
echo 2 > my_dir/file2.txt
gzip my_dir/file2.txt

# unpacking my_dir/file2.txt.gz...
mkdir -p temp_dir
gzip -c -d my_dir/file2.txt.gz > temp_dir/file2.txt

# doing something with data
cat temp_dir/*.txt > final.txt

如果再次调用(而没有进行清理),则输出将是make:final.txt‘是最新的。如果删除$(DEPS)文件,则相应的txt.gz文件将重新打包。如果删除了.txt.gz文件,.txt.gz文件将被重新创建并重新打包(因为它比现有的.txt文件更新)。

另外,如果您已经获得了要处理的所有*.txt.gz文件(如果缺少这些文件,则生成文件不必创建它们),则可以使用以下makefile:

代码语言:javascript
复制
COMPRESSED_DIR = my_dir
UNCOMPRESSED_DIR = temp_dir

# get a list of all *.txt.gz files within $(COMPRESSED_DIR)
ARCHIVES = $(wildcard $(COMPRESSED_DIR)/*.txt.gz)

# do some magic to modify $(ARCHIVES) into a list of *.txt files to produce
DEPS = $(subst $(COMPRESSED_DIR),$(UNCOMPRESSED_DIR),$(subst .txt.gz,.txt,$(ARCHIVES)))

##
##  Recipe to unpack compressed files
##
$(UNCOMPRESSED_DIR)/%.txt: $(COMPRESSED_DIR)/%.txt.gz
    @echo ""
    @echo "# unpacking $<..."
    mkdir -p $(UNCOMPRESSED_DIR)
    gzip -c -d $< > $@

##
##  Recipe to make final.txt
##
final.txt: $(DEPS)
    @echo "Archives:"
    @echo $(ARCHIVES)
    @echo ""
    @echo "Deps:"
    @echo $(DEPS)
    @echo ""
    @echo "# doing something with data"
    cat $(UNCOMPRESSED_DIR)/*.txt > final.txt

##
##  Recipe to clean
##
clean:
    rm -rf $(UNCOMPRESSED_DIR)
    rm -f final.txt

这个makefile将将COMPRESSED_DIR中的所有COMPRESSED_DIR文件解压缩为UNCOMPRESSED_DIR,并将所有*.txt文件解压到final.txt中。

票数 2
EN

Stack Overflow用户

发布于 2014-10-25 15:20:18

你可以一步一步地把枪拉链:

代码语言:javascript
复制
my_dir:
    [ -d $@ ] || mkdir -p $@

my_dir/%.txt.gz: my_dir
    @echo "# obtaining data for $@"
    echo $* | gzip -c > $@

final.txt: my_dir/*.txt.gz
    @echo "# doing something with data for $@"
    gunzip -c $+ > $@

clean:
    rm -rf my_dir final.txt

依赖项my_dir/*.txt.gz意味着final.txt将从任何匹配的文件中生成(如果没有匹配的文件,则会失败)。为了确保文件在不存在的情况下生成,您需要显式地列出它们,例如(如果使用GNU Make)

代码语言:javascript
复制
final.txt: $(foreach x,1 2 3 4 5 6 7 8,my_dir/$x.txt.gz)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26552925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档