我是make新手,所以可以随意更正我对这个问题的语法。
我想要创建一个makefile来下载一堆压缩文件,解压缩它们并对它们做一些事情。这是我的玩具例子:
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),就会得到一个错误:
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.txt和file2.txt的内容,但这些文件最初是压缩的。当有压缩文件时,我如何告诉make调用gzip,在未压缩文件可用时不做任何事情?
发布于 2014-10-24 19:39:25
经过一些实验,我创建了下面的makefile:
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:
# 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:
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中。
发布于 2014-10-25 15:20:18
你可以一步一步地把枪拉链:
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)
final.txt: $(foreach x,1 2 3 4 5 6 7 8,my_dir/$x.txt.gz)https://stackoverflow.com/questions/26552925
复制相似问题