【问题标题】:How to expand wildcard inside shell code block in a Makefile?如何在 Makefile 中的 shell 代码块内扩展通配符?
【发布时间】:2019-04-06 02:12:00
【问题描述】:

我得到了这个脚本,它读取我的.gitignore 文件的分隔部分并删除给定标记# # 之后的所有文件:

# https://stackoverflow.com/questions/55527923/how-to-stop-makefile-from-expanding-my-shell-output
RAW_GITIGNORE_CONTENTS := $(shell while read -r line; do printf "$$line "; done < ".gitignore")
GITIGNORE_CONTENTS := $(shell echo "$(RAW_GITIGNORE_CONTENTS)" | sed -E $$'s/[^\#]+\# //g')

# https://stackoverflow.com/questions/4210042/exclude-directory-from-find-command
DIRECTORIES_TO_CLEAN := $(shell /bin/find -not -path "./**.git**" -not -path "./pictures**" -type d)

clean:
#   https://stackoverflow.com/questions/10586153/split-string-into-an-array-in-bash
#   https://stackoverflow.com/questions/11289551/argument-list-too-long-error-for-rm-cp-mv-commands
    readarray -td' ' GARBAGE_DIRECTORIES <<<"$(DIRECTORIES_TO_CLEAN) "; \
    unset 'GARBAGE_DIRECTORIES[-1]'; \
    declare -p GARBAGE_DIRECTORIES; \
    readarray -td' ' GARBAGE_EXTENSIONS <<<"$(GITIGNORE_CONTENTS) "; \
    unset 'GARBAGE_EXTENSIONS[-1]'; \
    declare -p GARBAGE_EXTENSIONS; \
    for filename in "$${GARBAGE_DIRECTORIES[@]}"; \
    do \
        arraylength="$${#GARBAGE_EXTENSIONS[@]}"; \
        printf 'Cleaning %s extensions on %s\n' "$${arraylength}" "$$filename"; \
        for extension in "$${GARBAGE_EXTENSIONS[@]}"; \
        do \
            [[ ! -z "$$filename" ]] || continue; \
            [[ ! -z "$$extension" ]] || continue; \
            full_expression="$${filename}/$${extension}" ;\
            printf '%s\n' "$$full_expression"; \
            rm -v "$$full_expression"; \
        done; \
    done;

使用以下.gitignore 文件运行它:

*.txt
*.var
# Comment #
*.aux

rm 命令没有扩展通配符,并一直告诉我rm: cannot remove './*.aux': No such file or directory 并且不要从./ 目录中删除*.aux 文件。


更新

在询问@Beta 的评论后,我将Makefile 简化为:


GITIGNORE_CONTENTS := "*.aux" "*.lof"
DIRECTORIES_TO_CLEAN := "./setup/cache" "./setup/cache/chapters"

clean:
    readarray -td' ' GARBAGE_DIRECTORIES <<<"$(DIRECTORIES_TO_CLEAN) "; \
    unset 'GARBAGE_DIRECTORIES[-1]'; \
    declare -p GARBAGE_DIRECTORIES; \
    readarray -td' ' GARBAGE_EXTENSIONS <<<"$(GITIGNORE_CONTENTS) "; \
    unset 'GARBAGE_EXTENSIONS[-1]'; \
    declare -p GARBAGE_EXTENSIONS; \
    for filename in "$${GARBAGE_DIRECTORIES[@]}"; \
    do \
        arraylength="$${#GARBAGE_EXTENSIONS[@]}"; \
        printf 'Cleaning %s extensions on %s\n' "$${arraylength}" "$$filename"; \
        for extension in "$${GARBAGE_EXTENSIONS[@]}"; \
        do \
            [[ ! -z "$$filename" ]] || continue; \
            [[ ! -z "$$extension" ]] || continue; \
            full_expression="$${filename}/$${extension}" ;\
            printf '%s\n' "$$full_expression"; \
            rm -vf "$$full_expression"; \
        done; \
    done;

运行此输出后的结果:

$ make
readarray -td' ' GARBAGE_DIRECTORIES <<<""./setup/cache" "./setup/cache/chapters" "; \
unset 'GARBAGE_DIRECTORIES[-1]'; \
declare -p GARBAGE_DIRECTORIES; \
readarray -td' ' GARBAGE_EXTENSIONS <<<""*.aux" "*.lof" "; \
unset 'GARBAGE_EXTENSIONS[-1]'; \
declare -p GARBAGE_EXTENSIONS; \
for filename in "${GARBAGE_DIRECTORIES[@]}"; \
do \
        arraylength="${#GARBAGE_EXTENSIONS[@]}"; \
        printf 'Cleaning %s extensions on %s\n' "${arraylength}" "$filename"; \
        for extension in "${GARBAGE_EXTENSIONS[@]}"; \
        do \
                [[ ! -z "$filename" ]] || continue; \
                [[ ! -z "$extension" ]] || continue; \
                full_expression="${filename}/${extension}" ;\
                printf '%s\n' "$full_expression"; \
                rm -vf "$full_expression"; \
        done; \
done;
declare -a GARBAGE_DIRECTORIES=([0]="./setup/cache" [1]="./setup/cache/chapters")
declare -a GARBAGE_EXTENSIONS=([0]="*.aux" [1]="*.lof")
Cleaning 2 extensions on ./setup/cache
./setup/cache/*.aux
./setup/cache/*.lof
Cleaning 2 extensions on ./setup/cache/chapters
./setup/cache/chapters/*.aux
./setup/cache/chapters/*.lof

更简单

我简化为更简单的版本:

clean:
    rm -v "./setup/cache/*.aux";

运行这个,也不要删除文件:

$ make
rm -v "./setup/cache/*.aux";
rm: cannot remove './setup/cache/*.aux': No such file or directory
make: *** [Makefile:3: clean] Error 1

$ ls ./setup/cache/*.aux
./setup/cache/main.aux

在上面,运行ls后,你可以看到文件仍然存在,它就在那里。

【问题讨论】:

  • 你看到了什么命令?当你simplify the makefile 时会发生什么?
  • @Beta 我更新了问题,尽可能简化。
  • ...然后您轻松找到了该错误。现在你明白为什么我们建议人们简化他们的代码了。
  • @Beta,感谢您的帮助!如果您知道它为什么起作用,您可以发布作为答案!
  • Bash 扩展了 unquoted 通配符。没有双引号,命令rm *aux 变为rm main.aux,但带有双引号rm 尝试删除名为*.aux 的文件,并且没有这样的文件。

标签: shell makefile wildcard expansion


【解决方案1】:

我设法通过更改来修复它:

    rm -vf "$$full_expression"; \

收件人:

    rm -vf $${full_expression}; \

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    相关资源
    最近更新 更多